Jackson 流API
Contents
1 . 概述
在本文中,我们将研究 Jackson Streaming API。它支持读写,通过使用它,我们可以编写高性能、快速的 JSON 解析器。 另一方面,它有点难以使用——JSON 数据的每个细节都需要在代码中明确处理。
2. Maven依赖
首先,我们需要向jackson-core 添加一个 Maven 依赖项:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.1</version>
</dependency>
3. 写入 JSON
我们可以使用*JsonGenerator 类将 JSON 内容直接写入OutputStream* 。首先,我们需要创建该对象的实例:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonFactory jfactory = new JsonFactory();
JsonGenerator jGenerator = jfactory
.createGenerator(stream, JsonEncoding.UTF8);
接下来,假设我们要编写具有以下结构的 JSON:
{
"name":"Tom",
"age":25,
"address":[
"Poland",
"5th avenue"
]
}
我们可以使用JsonGenerator的实例将特定字段直接写入OutputStream:
jGenerator.writeStartObject();
jGenerator.writeStringField("name", "Tom");
jGenerator.writeNumberField("age", 25);
jGenerator.writeFieldName("address");
jGenerator.writeStartArray();
jGenerator.writeString("Poland");
jGenerator.writeString("5th avenue");
jGenerator.writeEndArray();
jGenerator.writeEndObject();
jGenerator.close();
要检查是否创建了正确的 JSON,我们可以创建一个包含 JSON 对象的String对象:
String json = new String(stream.toByteArray(), "UTF-8");
assertEquals(
json,
"{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}");
4.解析JSON
当我们得到一个 JSON字符串作为输入,并且我们想从中提取特定字段时,可以使用*JsonParser *类:
String json
= "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}";
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createParser(json);
String parsedName = null;
Integer parsedAge = null;
List<String> addresses = new LinkedList<>();
我们想从输入的 JSON中获取parsedName、parsedAge和addresses字段。为此,我们需要处理底层的解析逻辑并自己实现:
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("name".equals(fieldname)) {
jParser.nextToken();
parsedName = jParser.getText();
}
if ("age".equals(fieldname)) {
jParser.nextToken();
parsedAge = jParser.getIntValue();
}
if ("address".equals(fieldname)) {
jParser.nextToken();
while (jParser.nextToken() != JsonToken.END_ARRAY) {
addresses.add(jParser.getText());
}
}
}
jParser.close();
根据字段名称,我们将其提取并分配给适当的字段。解析文档后,所有字段都应该有正确的数据:
assertEquals(parsedName, "Tom");
assertEquals(parsedAge, (Integer) 25);
assertEquals(addresses, Arrays.asList("Poland", "5th avenue"));
5. 提取 JSON 部分
有时,当我们解析 JSON 文档时,我们只对一个特定字段感兴趣。 理想情况下,在这些情况下,我们只想解析文档的开头,一旦找到需要的字段,我们就可以中止处理。 假设我们只对输入 JSON的*年龄字段感兴趣。*在这种情况下,我们可以实现解析逻辑,一旦找到需要的字段就停止解析:
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("age".equals(fieldname)) {
jParser.nextToken();
parsedAge = jParser.getIntValue();
return;
}
}
jParser.close();
处理后,唯一的parsedAge字段将有一个值:
assertNull(parsedName);
assertEquals(parsedAge, (Integer) 25);
assertTrue(addresses.isEmpty());
多亏了这一点,JSON 文档的解析会快很多,因为我们不需要读取整个文档,只需要读取其中的一小部分。