ジャクソンストリーミングAPI

Jackson Streaming API

Javaエコシステムで数年の経験があり、その経験をコミュニティと共有することに興味がある場合(そしてもちろん、あなたの仕事に対して報酬を得ることに興味がある場合)、"Write for Us" pageを見てください。 乾杯。 オイゲン

1. Overview

この記事では、Jackson Streaming APIについて説明します。 読み取りと書き込みの両方をサポートし、それを使用することで、高性能で高速なJSONパーサーを作成できます。

一方、使用するのは少し難しいです。JSONデータのすべての詳細をコードで明示的に処理する必要があります。

2. メーベン依存

まず、Mavenの依存関係をjackson-coreに追加する必要があります。


    com.fasterxml.jackson.core
    jackson-core
    2.9.4

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の解析

JSONStringを入力として取得し、そこから特定のフィールドを抽出する場合は、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 addresses = new LinkedList<>();

入力JSONからparsedName, parsedAge, and 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ドキュメントを解析するときに、特定の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からStream ProcessingAPIを活用する方法を見ていきます。

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