3

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?

1
  • @hexin I am working with GSON and I guess above example don't use GSON. Commented Jun 17, 2014 at 7:25

4 Answers 4

3

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);
   }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Vach. How would I do this in Java7? I am working Java7 as of now.
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?
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)
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...

Comments

0

You may want to parse all the objects, and then filter the ones you're interested in.

After you've obtained jArray, try:

//get json array from json string
JsonArray jarray = jobject.getAsJsonArray("reportRecords");

//get a list of reportRecords using Gson
Gson mGson = new Gson();
Type listType = new TypeToken<List<DataMetrics>>(){}.getType();
List<DataMetrics> dataMetricsList = mGson.fromJson(reportRecordsJsonArray, listType);

//Filter only the ones with a specific name
List<DataMetrics> dataMetricsFilteredList = dataMetricsList.stream().filter(dataMetric -> dateMetric.getName.equals("Client::Sync"));

Comments

-2

i didn't try it but it may work.

 public void getFromJson(JSONObject json)
         {
             JSONArray jarray = (JSONArray) json.get("reportRecords");
             List<DataMetrics> myList = new ArrayList();
             for(int i = 0; i < jarray.size(); i++)
             {
                 myList.add((DataMetrics) getClassFromJsonObject((JSONObject) jarray.get(i),
 DataMetrics.class));
             }
         }

//// public Object getClassFromJsonObject(JSONObject json, Class myClass){

    Object object = new Object();
    ObjectMapper obj =  JSONMapperFactory.createMapper();
    obj.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    try {
        object = obj.readValue(json.toString(), myClass);
    } catch (IOException e) {
        e.printStackTrace();  
        throw new RuntimeException(e);
    }
    return myClass.cast(object);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.