使用Java(Jackson)读取JSON中嵌套键的值

Jon*_*n.H 28 java json jackson gson

我是来自Python背景的新Java程序员.我有收集/返回的天气数据作为带有嵌套键的JSON,我不明白在这种情况下如何拉出值.我确定之前已经问过这个问题,但是我发誓我用Google搜索了很多内容,我似乎无法找到答案.现在我正在使用json-simple,但我尝试切换到Jackson,但仍然无法弄清楚如何做到这一点.由于Jackson/Gson似乎是最常用的库,我很乐意看到使用其中一个库的示例.下面是数据的示例,后面是我到目前为止编写的代码.

{
    "response": {
        "features": {
            "history": 1
        }
     },
    "history": {
        "date": {
            "pretty": "April 13, 2010",
            "year": "2010",
            "mon": "04",
            "mday": "13",
            "hour": "12",
            "min": "00",
            "tzname": "America/Los_Angeles"
        },
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

主功能

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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

函数'historical'调用另一个返回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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Sta*_*Man 63

使用Jackson的树模型(JsonNode),你有两个"文字"访问器方法('get'),它返回null缺失值,以及"安全"访问器('path'),它允许你遍历"丢失"节点.所以,例如:

JsonNode root = mapper.readTree(inputSource);
int h = root.path("response").path("history").getValueAsInt();
Run Code Online (Sandbox Code Playgroud)

这将返回给定路径的值,或者,如果缺少路径,则为0(默认值)

但更方便的是,您可以使用JSON指针表达式:

int h = root.at("/response/history").getValueAsInt();
Run Code Online (Sandbox Code Playgroud)

还有其他方法,通常将结构实际建模为Plain Old Java Object(POJO)更方便.您的内容可能类似于:

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
}
Run Code Online (Sandbox Code Playgroud)

如果是这样,您将像任何Java对象一样遍历结果对象.

  • 由于Java是静态类型的,与Python(或者更多)不同,我认为POJO模型更适合自然,因为您随后处理基本的Java对象,而不用担心JSON部分.您只需定义与JSON对齐的对象,并且库(Jackson,GSON)可以从一个转换为另一个.如果是这样,所有构造,操纵,更改数据都会发生在POJO中,并且转换为JSON或从JSON转换是单独的自动序列化步骤.一些开发人员发现这更简单,更自然,而其他人更喜欢更动态的树访问.因此,其中一部分用于偏好,另一部分用于用例. (2认同)

小智 6

使用Jsonpath

整数h = JsonPath.parse(json).read(“ $。response.repository.history”,Integer.class);