How to iterate JSON Array and extract each JSON Object from it using GSON?

18,293

Solution 1

So you have the JsonArray object with your records, here's what you do to get your functional objects:

Type type = new TypeToken<List<DataMetrics>>() {}.getType();
List<DataMetrics> records = gson.fromJson(jsonArrayThatYouHave, type);

Then you iterate through you objects and filter the ones you need. In java 8 you can do this:

List<DataMetrics> result = records.stream().filter(record -> record.name.equals("Client::Sync")).collect(toList());

This approach is converting all objects and iterating after, if exactly this part of code is performance critical, you can still iterate through json and convert only necessary objects (but i doubt that this will be actually faster than described above).

Anyway this is more maintainable and understandable code.

UPDATE:

the same for java 7 will be:

List<DataMetrics> result = new LinkedList<>();

for(DataMetrics record : records){
   if(record.name.equals("Client::Sync")){
      result.add(record);
   }
}

Solution 2

Or if you want to iterate json and parse only required ones heres what you can do:

Type type = new TypeToken<List<DataMetrics>>() {}.getType();

for(JsonElement elem : jsonArrayThatYouHave) {
   if (elem.getAsJsonObject().get("name").getAsString().equals("Client::Sync")) {
      result.add(gson.fromJson(elem, type));
   }
}

but I dont think this is actually faster than the first one because in both cases you are converting json to java functional object with parser and getting JsonArray or anything else. Taking into consideration the fact that both are Googles libs, i assume that parsing from JsonObject to some specific type with gson is way faster than from String (raw json) to the same specific type...

Share:
18,293
john
Author by

john

Updated on July 20, 2022

Comments

  • john
    john almost 2 years

    Below is my JSON String which I am getting back by calling from a service API. I have shorten it down by having only three reportRecords for the understanding purpose. In general, it might have ~500 reportRecords

    {
       "aggRecords": {
          "reportRecords": [
             {
                "min": 0,
                "max": 12,
                "avg": 0.3699187,
                "count": 246,
                "sumSq": 571,
                "stddev": 1.4779372,
                "median": 0,
                "percentileMap": {
                   "95": 4
                },
                "metricName": "TransactionDuration",
                "dimensions": {
                   "env": "dev",
                   "pool": "titan",
                   "Name": "PostProcessing",
                   "Type": "PostProcessing"
                },
                "value": 91
             },
             {
                "min": 0,
                "max": 23,
                "avg": 2.3991289E-4,
                "count": 1463031,
                "sumSq": 3071,
                "stddev": 0.045814946,
                "median": 0,
                "percentileMap": {
                   "95": 0
                },
                "metricName": "TransactionDuration",
                "dimensions": {
                   "env": "dev",
                   "pool": "titan",
                   "Name": "ResourceContext",
                   "Type": "ResourceContext"
                },
                "value": 351
             },
             {
                "min": 0,
                "max": 1209,
                "avg": 1.9203402,
                "count": 7344636,
                "sumSq": 71832774,
                "stddev": 2.4683187,
                "median": 2,
                "percentileMap": {
                   "95": 4
                },
                "metricName": "TransactionDuration",
                "dimensions": {
                   "env": "dev",
                   "pool": "titan",
                   "Name": "Client::Sync",
                   "Type": "Client::Sync"
                },
                "value": 14104200
             }
          ]
       },
       "minRecordsMap": {}
    }
    

    Now From the above JSON response, I need to extract reportRecords whose Name is Client::Sync. Meaning, I need to extract below reportRecords from the above JSON response only.

             {
                "min": 0,
                "max": 1209,
                "avg": 1.9203402,
                "count": 7344636,
                "sumSq": 71832774,
                "stddev": 2.4683187,
                "median": 2,
                "percentileMap": {
                   "95": 4
                },
                "metricName": "TransactionDuration",
                "dimensions": {
                   "env": "dev",
                   "pool": "titan",
                   "Name": "Client::Sync",
                   "Type": "Client::Sync"
                },
                "value": 14104200
             }
    

    And now I need to parse the above reportRecords for Client::Sync to below object -

    public class DataMetrics {
    
        private String pool;
        private String name;
        private String type;
        private String env;
        private String metricName;
        private String percentile;
        private String median;
        private String stdDev;
        private String sumSq;
        private String count;
        private String avg;
        private String max;
        private String min;
    
        // getters and setters here
    }
    

    Above variable, maps like this -

    pool is titan
    name is Client::Sync 
    type is Client::Sync
    env is dev
    metricNname is TransactionDuration
    95th  percentile is 4
    median is 2
    stdDev is 2.4683187 
    sumSq is 71832774 
    count is 7344636 
    avg is 1.9203402
    max is 1209
    min is 0
    

    I am using GSON library here and below is what I have tried so far -

    private static RestTemplate restTemplate = new RestTemplate();
    
    public static void main(String[] args) {
    
        String jsonLine = restTemplate.getForObject("some_url", String.class);
        System.out.println(jsonLine); // here jsonLine will give me above big JSON String
    
        JsonElement jelement = new JsonParser().parse(jsonLine);
        JsonObject  jobject = jelement.getAsJsonObject();
        jobject = jobject.getAsJsonObject("aggRecords");
        JsonArray jarray = jobject.getAsJsonArray("reportRecords");
    
        // now how do I iterate JsonArray and get each JSON object
        // and then check "name" property of each object, if "Client::Sync" found, read that object for all properties
        // and set it using setters.
    
    }
    

    Now I am not able to understand how do I iterate JsonArray and extract each JSON object from it?

  • john
    john almost 10 years
    Thanks Vach. How would I do this in Java7? I am working Java7 as of now.
  • john
    john almost 10 years
    Thanks for the help. I tried this and somehow most of the fields are coming as empty like percentile, name, type, min and few other but some has the data. Do you see anything wrong?
  • vach
    vach almost 10 years
    You just need the same names of Class properties as in json (or specify it with @Qualifier annotation if you dont want to change it)