ジャクソンストリーミングAPI
1
概要
この記事では、Jackson Streaming APIを見ていきます。読み取りと書き込みの両方をサポートしており、それを使用することで、高性能で高速なJSONパーサーを作成できます。
一方、JSONデータの詳細はすべてコードで明示的に処理する必要があります。
2 Mavenの依存関係
まず、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.fasterxml.jackson.core%22%20AND%20a%3A%にMaven依存関係を追加する必要があります。 22jackson-databind%22[
jackson-core
]:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</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、および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 Processing APIをどのように利用できるかを調べています。
これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/jackson[GitHubに追加] – これはMavenプロジェクトなので、インポートして実行するのは簡単なはずです。そのまま。