Jackson 流媒體 API

Data,Jackson
Remote
0
12:15 AM · Dec 01 ,2025

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。

發佈 評論

Some HTML is okay.