使用 Java 读取 JSON 中嵌套键的值 (Jackson)
Reading value of nested key in JSON with Java (Jackson)
我是一名来自 Python 的新 Java 程序员。我的天气数据 collected/returned 为 JSON,里面有嵌套的键,我不明白在这种情况下如何提取这些值。我确定以前有人问过这个问题,但我发誓我已经用谷歌搜索了很多,但似乎找不到答案。现在我正在使用 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"
},
...
}
}
主要功能
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"));
}
}
函数 'historical' 调用另一个函数 returns 一个 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();
}
}
查看 Jackson 的 ObjectMapper。您可以创建一个 class 来为您的 JSON 建模,然后使用 ObjectMapper 的 readValue 方法将您的 JSON 字符串 'deserialize' 转换为您的模型实例 class。反之亦然。
使用 Jackson 树模型 (JsonNode
),您有两个 "literal" 访问器方法 ('get'),其中 returns null
用于缺失值和 "safe" 访问器 ('path'),它们允许您遍历 "missing" 个节点。所以,例如:
JsonNode root = mapper.readTree(inputSource);
int h = root.path("response").path("history").getValueAsInt();
这将 return 给定路径的值,或者,如果缺少路径,则为 0(默认值)
但更方便的是,您可以只使用 JSON 指针表达式:
int h = root.at("/response/history").getValueAsInt();
还有其他方法,通常将您的结构实际建模为普通旧 Java 对象 (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
}
如果是这样,您将像遍历任何 Java 个对象一样遍历结果对象。
使用Jsonpath
整数 h = JsonPath.parse(json).read("$.response.repository.history", Integer.class);
尝试 jpath API。它相当于 JSON 数据的 xpath。您可以通过提供将遍历 JSON 数据和 return 请求值的 jpath 来读取数据。
这个 Java class 是实现以及它有关于如何调用 APIs 的示例代码。
https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java
自述文件 -
https://github.com/satyapaul/jpath/blob/master/README.md
示例:
JSON数据:
{
"data": [{
"id": "13652355666_10154605514815667",
"uid": "442637379090660",
"userName": "fanffair",
"userFullName": "fanffair",
"userAction": "recommends",
"pageid": "usatoday",
"fanPageName": "USA TODAY",
"description": "A missing Indonesian man was found inside a massive python on the island of Sulawesi, according to local authorities and news reports. ",
"catid": "NewsAndMedia",
"type": "link",
"name": "Indonesian man swallowed whole by python",
"picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"full_picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"message": "Akbar Salubiro was reported missing after he failed to return from harvesting palm oil.",
"link": "http:\/\/www.usatoday.com\/story\/news\/nation-now\/2017\/03\/29\/missing-indonesian-man-swallowed-whole-reticulated-python\/99771300\/",
"source": "",
"likes": {
"summary": {
"total_count": "500"
}
},
"comments": {
"summary": {
"total_count": "61"
}
},
"shares": {
"count": "4"
}
}]
}
代码片段:
String jPath = "/data[Array][1]/likes[Object]/summary[Object]/total_count[String]";
String value = JSONDataReader.getStringValue(jPath, jsonData);
我是一名来自 Python 的新 Java 程序员。我的天气数据 collected/returned 为 JSON,里面有嵌套的键,我不明白在这种情况下如何提取这些值。我确定以前有人问过这个问题,但我发誓我已经用谷歌搜索了很多,但似乎找不到答案。现在我正在使用 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"
},
...
}
}
主要功能
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"));
}
}
函数 'historical' 调用另一个函数 returns 一个 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();
}
}
查看 Jackson 的 ObjectMapper。您可以创建一个 class 来为您的 JSON 建模,然后使用 ObjectMapper 的 readValue 方法将您的 JSON 字符串 'deserialize' 转换为您的模型实例 class。反之亦然。
使用 Jackson 树模型 (JsonNode
),您有两个 "literal" 访问器方法 ('get'),其中 returns null
用于缺失值和 "safe" 访问器 ('path'),它们允许您遍历 "missing" 个节点。所以,例如:
JsonNode root = mapper.readTree(inputSource);
int h = root.path("response").path("history").getValueAsInt();
这将 return 给定路径的值,或者,如果缺少路径,则为 0(默认值)
但更方便的是,您可以只使用 JSON 指针表达式:
int h = root.at("/response/history").getValueAsInt();
还有其他方法,通常将您的结构实际建模为普通旧 Java 对象 (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
}
如果是这样,您将像遍历任何 Java 个对象一样遍历结果对象。
使用Jsonpath
整数 h = JsonPath.parse(json).read("$.response.repository.history", Integer.class);
尝试 jpath API。它相当于 JSON 数据的 xpath。您可以通过提供将遍历 JSON 数据和 return 请求值的 jpath 来读取数据。
这个 Java class 是实现以及它有关于如何调用 APIs 的示例代码。
https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java
自述文件 -
https://github.com/satyapaul/jpath/blob/master/README.md
示例:
JSON数据:
{
"data": [{
"id": "13652355666_10154605514815667",
"uid": "442637379090660",
"userName": "fanffair",
"userFullName": "fanffair",
"userAction": "recommends",
"pageid": "usatoday",
"fanPageName": "USA TODAY",
"description": "A missing Indonesian man was found inside a massive python on the island of Sulawesi, according to local authorities and news reports. ",
"catid": "NewsAndMedia",
"type": "link",
"name": "Indonesian man swallowed whole by python",
"picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"full_picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"message": "Akbar Salubiro was reported missing after he failed to return from harvesting palm oil.",
"link": "http:\/\/www.usatoday.com\/story\/news\/nation-now\/2017\/03\/29\/missing-indonesian-man-swallowed-whole-reticulated-python\/99771300\/",
"source": "",
"likes": {
"summary": {
"total_count": "500"
}
},
"comments": {
"summary": {
"total_count": "61"
}
},
"shares": {
"count": "4"
}
}]
}
代码片段:
String jPath = "/data[Array][1]/likes[Object]/summary[Object]/total_count[String]";
String value = JSONDataReader.getStringValue(jPath, jsonData);