Use Java (JSON) to read the values of nested keys in JSON
I am a new Java programmer with Python background I have weather data being collected / returned in JSON, which contains nested keys. I don't understand how to pull out values in this case I believe this question has been asked before, but I swear I have Google a lot, and I can't seem to find the answer Now I use JSON simple, but I try to switch to Jackson, but I still can't figure out how to do this Since Jackson / gson seems to be the most commonly used library, I would like to see an example of using these libraries The following is the data sample, followed by the code I have 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 jsonobject
public static JSONObject readJsonFromUrl(URL url) throws MalformedURLException,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(); } }
Solution
Using Jackson's tree model (jsonnode), you have two "text" accessor methods ('Get '), which return null for missing values, and the "safe" accessor ('path') allows you to traverse the "lost" node So, for example:
JsonNode root = mapper.readTree(inputSource); int h = root.path("response").path("history").getValueAsInt();
This returns the value on the given path, or 0 if the path is missing (the default)
But more conveniently, you can use JSON pointer expressions:
int h = root.at("/response/history").getValueAsInt();
There are other methods, usually more practical, to simulate your structure as a common Java object (POJO) Your content may be suitable for:
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 }
If so, you will traverse the result object like any Java object