Ĵ AVA小号CRIPT ö bject Ñ otion( JSON)是事实上的用于在网页API交换数据的标准。JSON是一种递归数据结构,可以可视化为键值对树。
从JSON读取信息的API有两大类:
Streaming Based: 部分解析或访问JSON。每次零件迭代时,您将零件跳过或映射到对象。部分也许{,[, field,value,:,},和] (JSON令牌!)。
{,[, field,value,:,}
_Binding based:_绑定是JSON字段到编程对象的映射;这些可能是领域的或抽象的。 JSON完全解析并映射到对象。 本文介绍了读取JSON数据的不同模式。选择Java来演示这些模式。
JSON —抽象模型绑定 JSON映射到中间提供的对象或集合对象的库。然后,迭代这些对象以与域对象进行映射或提取信息。
这些中间对象在形式上统称为“解析树”。将JSON转换为解析树的过程称为parsing²。
这些对象不能充分表达业务知识。这就是调用这些对象的原因:抽象。
In Action 考虑一下示例Google Distance Matrix API的输出中纽约和华盛顿之间的提取距离:
{ "destination_addresses" : [ "New York, NY, USA" ], "origin_addresses" : [ "Washington, DC, USA" ], "rows" : [ { "elements" : [ { "distance" : { "text" : "225 mi", "value" : 361715 }, "duration" : { "text" : "3 hours 49 mins", "value" : 13725 }, "status" : "OK" } ] } ], "status" : "OK" }
GSON是解析JSON的库之一。提取距离的代码如下:
JsonParser parser = new JsonParser(); // tree object structure is provided by lib. JsonElement parsedTree = parser.parse(json); JsonObject root = parsedTree.getAsJsonObject(); JsonObject firstRow = root.get("rows").getAsJsonArray().get(0).getAsJsonObject(); JsonObject firstElement = firstRow.get("elements").getAsJsonArray().get(0).getAsJsonObject(); // finally, distance is extracted ! Phew String distance = firstElement.get("distance").getAsJsonObject().get("value").getAsString();
Repl.it→ https: //repl.it/@DM8tyProgrammer/NonDomainBinding
JSON —域模型绑定 几乎整个JSON都直接映射到等效的Domain或Business Objects;域对象模仿具有相同字段和兼容类型的JSON结构。
In Action 考虑来自Web API的Twitter的Tweet对象,以演示此模式。
{ "created_at": "Wed Oct 10 20:19:24 +0000 2018", "id": 1050118621198921728, "id_str": "1050118621198921728", "text": "To make room for more expression, we will now count all emojis as equal—including those with gender and skin t… https://t.co/MkGjXf9aXm", "user": {...} . . . }
等效类适用于上述JSON:
class Tweet { private long id; private String id_str; private String text; private String source; private User user; private String created_at; }
{ "user": { "id": 6253282, "id_str": "6253282", "name": "Twitter API", "screen_name": "TwitterAPI", "location": "San Francisco, CA", "url": "https://developer.twitter.com", "description": "The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website." . } }
class User { private long id; private String id_str; private String name; private String description; private String screen_name; private String url; private String location; }
您可以验证:类具有相同名称和兼容类型的逐字段镜像JSON。一些库在映射方面提供了放宽:缺少的字段,未知的字段,字段名称不匹配,类型不匹配和转换。
Jackson是著名的领域对象映射库。Jackson提供了一个ObjectMapper API来读取或写入JSON。映射代码为:
ObjectMapper objectMapper = new ObjectMapper(); Tweet tweet = objectMapper.readValue(tweetAsJson, Tweet.class); // process Tweet object
Repl.it→ https: //repl.it/@DM8tyProgrammer/jackson 基于表达式的数据提取 可以使用JSONPath提取JSON中的选定数据,JSONPath 是用于指向字段的代数表达式。XPath启发了JSONPath的想法。
使用JSONPath的提取可以描述为:
JSONPath表达式 在JSONPath上下文中,JSON被视为Tree。将以下元素串联起来以表达表达式:
$
.
..
['<field name>']
[<number>]
[*]
In Action 再次,从示例Google Distance Matrix API的输出中考虑纽约和华盛顿之间的提取距离:
The JSON path would be: $.rows[0].elements[0].distance.value. JSONPath can be evaluated with Jayway’s Jsonpath (notice name!) library. The code snippet for the extracting distance is as:
ReadContext ctx = JsonPath.parse(distanceJson); Double distance = ctx.read("$.rows[0].elements[0].distance.value", Double.class); Repl.it → https://repl.it/@DM8tyProgrammer/jsonpath
JSON Streaming Parsing 前面提到,流JSON意味着部分地迭代JSON。这些部分正式称为令牌。这些可以是单个字符或字符组。 In JSON Format Specification, the following tokens are defined:
{
}
[
]
(true, false), null
In Action 考虑一个简单的JSON来解析:
{ "name": "Mighty", "handler": "DM8typrogrammer" }
GSON和Jackson均具有Streaming API。杰克逊被任意选择进行示威。下面展示了通过流令牌解析JSON的代码;每次迭代时,数据将按以下方式推送到集合:
String json = "{\"name\": \"mighty\", \"handler\": \"DM8typrogrammer\"}"; JsonFactory jsonfactory = new JsonFactory(); JsonParser jsonParser = jsonfactory.createParser(json); // putting values in map Map<String, String> data = new HashMap<>(); JsonToken currentToken = jsonParser.nextToken(); while (currentToken != JsonToken.END_OBJECT) { if (currentToken == JsonToken.FIELD_NAME) { String fieldname = jsonParser.getCurrentName(); jsonParser.nextToken(); // move to value // pushing data to map data.put(fieldname, jsonParser.getText()); } // iterating token by token currentToken = jsonParser.nextToken(); } jsonParser.close(); System.out.println(data);
Repl.it→ https: //repl.it/@DM8tyProgrammer/stream-json
可以将代码理解为遍历具有JSON tokens:
结束语 Binding API在内部流式传输JSON,以将其转换为对象形式。可以说Binding是高级API。
流,抽象模型绑定和基于表达式的提取用于 从JSON选择数据的一部分。域模型绑定方法用于提取完整的JSON信息。
基于表达式的JSON提取是Abstract Model Binding方法的声明性变体 。您无需手动编写代码来解析树,而是将规范传递给API以从JSON提取数据。这是一种简洁灵活的方法;但是,它是一个较慢的变体。
原文链接:http://codingdict.com