javajsonarraylistgroovyjsonslurper

How to list json field names and values?


Please help me figure out the problem. I program in groovy (you can use a java example, it looks like there). Json comes to the input, in which it is not known how many fields. There can be 5 fields, maybe 10, maybe 50. My task is to process this json and return the data back using:

// Names of dataset columns
def names = ["a", "b", "c"];
// types of return values ​​in each column (for any field (column) json is always String)
def types = ["String", "String", "String"];
// formation of the dataset header
reader.outputLinesSetHeaders (names, types);
// Passing the data itself from json
reader.outputLines ([it.a, it.b, it.c])
// Close the dataset
reader.outputLinesEnd ();

If I knew the incoming json, then I would have set the required field names, the number of "String" in advance and returned their values by referring to a specific json field. The example below shows 3 json fields: auto, home, job. Accordingly, 3 times "String" for each of the fields and referring to a specific field to return the value of it.auto, it.home, it.job. But how can I do the same if I don't know the incoming json?

import groovy.json.JsonSlurper

import ru.itrpro.xm.plugins.groovy.ResultSetReader;

class XM_PARSE_XLS {

    def execute(ResultSetReader reader, String pfile) {



        def jsonSlurper = new JsonSlurper()
        def list = jsonSlurper.parseText(pfile)



        //The names of the columns of the dataset (now set statically to show an example; but in my case I don't know json and can't write it this way in advance)
        def names = ["AUTO", "HOME", "JOB"];
        //return types in each column (for any json, only "String" types)
        def types = ["String", "String", "String"];

        //формирование заголовка датасета
        reader.outputLinesSetHeaders(names,types);


                list.each {
                        //pass the values as a dataset from json (now set statically to show an example; but in my case I don't know json and can't write it this way in advance)
                        reader.outputLines([it?.AUTO, it?.HOME, it?.JOB]);
                }

        //closing dataset
        reader.outputLinesEnd();
        return null;



    }
    static void main(String... args) {
            String pfile =  """
[{"AUTO":"bmw",
  "HOME":"vest",
  "JOB":"bbds"},
  
  {"AUTO":"audi",
  "HOME":"dest",
  "JOB":"aads"},
  
  {"AUTO":"opel",
  "HOME":"lest",
  "JOB":"ffds"}]
"""
            def SSC = new XM_PARSE_XLS()
            def res = SSC.execute(new ResultSetReader(), pfile)

    }

}

Perhaps it is worth collecting all the field names of the incoming json into a list and specifying a list of "String" (any incoming json has all fields only "String") with the same number as the fields? But how to do this and how then should I pass the field values (it. ***)?


Solution

  • If the input JSON is of type Object (key-value pairs), it's parsed to a Map, so you can use it's methods to inspect it.

    import groovy.json.JsonSlurper
    
    String pfile =  """
    [{"AUTO":"bmw",
      "HOME":"vest",
      "JOB":1},
      
      {"AUTO":"audi",
      "HOME":"dest",
      "JOB":2},
      
      {"AUTO":"opel",
      "HOME":"lest",
      "JOB":3}]
    """
    def jsonSlurper = new JsonSlurper()
    def list = jsonSlurper.parseText pfile
    
    List names = list.inject( new HashSet() ){ res, map ->
      res.addAll map.keySet()
      res
    }.toList()
    
    // get types based on actual values
    def types = list.first().values()*.getClass()*.simpleName
    
    assert '[AUTO, JOB, HOME]' == names.toString()
    assert '[String, String, Integer]' == types.toString()
    
    //reader.outputLinesSetHeaders names, types
    
    list.each{ e ->
      //reader.outputLines names.collect{ e[ it ] }
      println names.collect{ e[ it ] }
    }
    
    //reader.outputLinesEnd()
    

    The lines are commented out to avoid compilation problems.