1. 概述
在本文中,我們將探討 Jackson 流式 API。它支持讀取和寫入,通過使用它,我們可以編寫高性能且快速的 JSON 解析器。
另一方面,它使用起來有點困難——JSON 數據中的每個細節都需要在代碼中顯式處理。
2. Maven 依賴
首先,我們需要將 Maven 依賴添加到 jackson-core:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.2</version>
</dependency>
3. 寫入 JSON
我們可以直接將 JSON 內容寫入 OutputStream,通過使用 JsonGenerator 類。首先,我們需要創建該對象的實例:
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 的 age 字段感興趣。在這種情況下,我們可以實現解析邏輯,以便在找到所需的字段後中止解析:
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 文檔的解析將更快,因為我們不需要讀取整個文檔,而是隻讀取其中的一部分。
6. 結論
在本文中,我們探討了如何利用 Jackson 的流式處理 API。