1 。 概要

この記事では、JacksonStreamingAPIについて説明します。 読み取りと書き込みの両方をサポートし、それを使用することで、高性能で高速な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 String を入力として取得し、そこから特定のフィールドを抽出する場合は、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、およびアドレスフィールドを取得します。 これを実現するには、低レベルの解析ロジックを処理し、それを自分で実装する必要があります。

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ドキュメントを解析するときに、特定の1つのフィールドだけに関心がある場合があります。

理想的には、このような状況では、ドキュメントの先頭のみを解析し、必要なフィールドが見つかったら、処理を中止できます。

入力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からStreamProcessingAPIを活用する方法を見ていきます。

これらすべての例とコードスニペットの実装は、GitHubにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。