2

I have an example nested json object like below :

{
"payload": {
"id": "1",
"apiResp": {
  "apiRespDetails": {
    "report": {
      "reportId": "reportid1",
      "reportDetails": [
        {
          "code": "1",
          "rating": "good"
        },
        {
          "code": "2",
          "rating": "bad"
        },
        {
          "code": "3",
          "rating": "fair"
        }
      ]
     }
   }
  }
 }
}

I only need the report object, I do not need any of its parent object details. What would be the best way to get just that using the Jackson API ?

I have created a Java Class called Report.java with fields reportId (String) and reportDetails(List of ReportDetail ) where ReportDetail is another class with String fields code , rating etc. Do I need to use some Deserializer, JsonTreeParser mechanism?Thanks.

NewQueries
  • 4,841
  • 11
  • 33
  • 39
  • You can just create respective parent objects and only capture what you are looking for – Coder Feb 08 '17 at 19:14
  • I don't think it will work like that. I will need to create a Java object for each of the nested objects. If there are 10 nested objects I do not want to add details of those in my class. – NewQueries Feb 08 '17 at 19:32
  • You can capture what you are looking for through the `@JsonProperty` and there are online implementations which generate all the Java objects if you simply paste your JSON. You can get rid of objects and elements you don't want – Coder Feb 08 '17 at 19:41

2 Answers2

1

The solution for this is jayway Java implementation for JsonPath.
JsonPath is the json equivalent for the XPath query language for XML. the query langauge is quite powerful, as can be seen in the examples on the github readme.

Here is a quick demo to get you started:

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import com.jayway.jsonpath.*;
import net.minidev.json.JSONArray;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.*;

public class JsonPathDemo2
{
    public static void main(String[] args)
    {
        // query: search for any report property below root 
        String jsonPathQuery = "$..report";

        try (InputStream is = Files.newInputStream(Paths.get("C://temp/xx.json"))) {
            Object parsedContent = 
                    Configuration.defaultConfiguration().jsonProvider().parse(is, StandardCharsets.UTF_8.name());
            System.out.println("hasJsonPath? " + hasJsonPath(jsonPathQuery).matches(parsedContent));
            Object obj = JsonPath.read(parsedContent, jsonPathQuery);
            System.out.println("parsed object is of type " + obj.getClass());
            System.out.println("parsed object to-string " + obj);
            JSONArray arr = (JSONArray)obj;
            System.out.println("first array item is of type " + arr.get(0).getClass());
            System.out.println("first array item to-string " + arr.get(0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

output:

hasJsonPath? true
parsed object is of type class net.minidev.json.JSONArray
parsed object to-string [{"reportId":"reportid1","reportDetails":[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}]
first array item is of type class java.util.LinkedHashMap
first array item to-string {reportId=reportid1, reportDetails=[{"code":"1","rating":"good"},{"code":"2","rating":"bad"},{"code":"3","rating":"fair"}]}
Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
  • Hi thanks for your response. I was looking for something in the jackson api. I found the answer to it. I will put the solution here. Thanks though. – NewQueries Feb 10 '17 at 15:10
1

Hi found two solutions using jackson fasterxml api.

In the first one you can just use the findValue method on the jsonNode and pass in the string value of property/object you are looking for

    String jsonresponse = "above json string";
    JsonFactory jsonFactory = new JsonFactory();
    JsonParser jp = jsonFactory.createParser(jsonresponse);
    jp.setCodec(new ObjectMapper());
    JsonNode jsonNode = jp.readValueAsTree();
    JsonNode reportNode = jsonNode.findValue("report");     
    ObjectMapper mapper = new ObjectMapper();
    Report report = mapper.convertValue(reportNode, Report.class);

This other solution use JsonToken which travels the json response till you find what you are looking for

    JsonFactory factory = new JsonFactory();       
    factory.setCodec(new ObjectMapper());
    JsonParser  parser  = factory.createParser(jsonresponse);
    while(!parser.isClosed()){
        JsonToken jsonToken = parser.nextToken();

        if(JsonToken.FIELD_NAME.equals(jsonToken)){
            String fieldName = parser.getCurrentName();
            if("report".equals(fieldName)) {
                jsonToken = parser.nextToken();
                Report report = parser.readValueAs(Report.class);       
            } else {
                jsonToken = parser.nextToken();
            }
        }
    } 
NewQueries
  • 4,841
  • 11
  • 33
  • 39