Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading value of nested key in JSON with Java (Jackson)

I'm a new Java programmer coming from a background in Python. I have weather data that's being collected/returned as a JSON with nested keys in it, and I don't understand how pull the values out in this situation. I'm sure this question has been asked before, but I swear I've Googled a great deal and I can't seem to find an answer. Right now I'm using json-simple, but I tried switching to Jackson and still couldn't figure out how to do this. Since Jackson/Gson seem to be the most used libraries, I'd would love to see an example using one of those libraries. Below is a sample of the data, followed by the code I've written so far.

{     "response": {         "features": {             "history": 1         }      },     "history": {         "date": {             "pretty": "April 13, 2010",             "year": "2010",             "mon": "04",             "mday": "13",             "hour": "12",             "min": "00",             "tzname": "America/Los_Angeles"         },         ...     } } 

Main function

public class Tester {      public static void main(String args[]) throws MalformedURLException, IOException, ParseException {         WundergroundAPI wu =  new WundergroundAPI("*******60fedd095");          JSONObject json = wu.historical("San_Francisco", "CA", "20100413");          System.out.println(json.toString());         System.out.println();         //This only returns 1 level. Further .get() calls throw an exception         System.out.println(json.get("history"));     } } 

The function 'historical' calls another function that returns a JSONObject

public static JSONObject readJsonFromUrl(URL url) throws MalformedURLException, IOException, ParseException {      InputStream inputStream = url.openStream();      try {         JSONParser parser = new JSONParser();         BufferedReader buffReader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));          String jsonText = readAll(buffReader);         JSONObject json = (JSONObject) parser.parse(jsonText);         return json;     } finally {         inputStream.close();     } } 
like image 652
Jon.H Avatar asked Apr 24 '15 22:04

Jon.H


People also ask

How does Jackson read nested JSON?

A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.

How do I Map nested values with Jackson?

Mapping With Annotations To map the nested brandName property, we first need to unpack the nested brand object to a Map and extract the name property. To map ownerName, we unpack the nested owner object to a Map and extract its name property.

What is the use of @JsonProperty?

@JsonProperty is used to mark non-standard getter/setter method to be used with respect to json property.

How do I ignore JsonProperty?

To ignore individual properties, use the [JsonIgnore] attribute. You can specify conditional exclusion by setting the [JsonIgnore] attribute's Condition property. The JsonIgnoreCondition enum provides the following options: Always - The property is always ignored.


2 Answers

With Jackson's tree model (JsonNode), you have both "literal" accessor methods ('get'), which returns null for missing value, and "safe" accessors ('path'), which allow you to traverse "missing" nodes. So, for example:

JsonNode root = mapper.readTree(inputSource); int h = root.path("response").path("history").getValueAsInt(); 

which would return the value at given path, or, if path is missing, 0 (default value)

But more conveniently, you can just use JSON pointer expression:

int h = root.at("/response/history").getValueAsInt(); 

There are other ways too, and often it is more convenient to actually model your structure as Plain Old Java Object (POJO). Your content could fit something like:

public class Wrapper {   public Response response; }  public class Response {   public Map<String,Integer> features; // or maybe Map<String,Object>   public List<HistoryItem> history; } public class HistoryItem {   public MyDate date; // or just Map<String,String>   // ... and so forth } 

and if so, you would traverse resulting objects just like any Java objects.

like image 163
StaxMan Avatar answered Sep 29 '22 03:09

StaxMan


Use Jsonpath

Integer h = JsonPath.parse(json).read("$.response.repository.history", Integer.class);

like image 31
Atmaram Avatar answered Sep 29 '22 02:09

Atmaram