Jackson JSON Processor

データの処理方法

JacksonはJSONを処理するのに、次の3つの方法を提供しています。

ダウンロード

Jacksonで必要とされるJARファイルは、その用途によって複数に分割されています。Streaming APIだけならば、

  • jackson-core

Tree ModelやData Bindingを用いるならば、

  • jackson-databind
  • jackson-annotations

も必要となります。

JacksonDownload - FasterXML Wiki

なおJackson 2.2のJavadocは、それぞれ

jackson-core https://fasterxml.github.io/jackson-core/javadoc/2.2.0/
jackson-databind https://fasterxml.github.io/jackson-databind/javadoc/2.2.0/
jackson-annotations https://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/

にあります。

Streaming API

Streaming APIはデータを順に読み込みながら処理するため、最もパフォーマンスの良い方法ですが、特定の要素を取得するような用途には不向きです。

  • 読み込み … org.codehaus.jackson.JsonParser
  • 書き込み … org.codehaus.jackson.JsonGenerator

読み込み

String data = "{\"a\":123,\"b\":true}";

JsonFactory factory = new JsonFactory();
try {
    JsonParser parser = factory.createParser(data);
    while (parser.nextToken() != JsonToken.END_OBJECT) {

        String name = parser.getCurrentName();
        JsonToken token = parser.getCurrentToken();

        System.out.println(name + ":" + token);
    }
} catch (IOException e) {
    e.printStackTrace();
}

これを実行すると、

null:START_OBJECT
a:FIELD_NAME
a:VALUE_NUMBER_INT
b:FIELD_NAME
b:VALUE_TRUE

のように出力されます。

JsonToken (Jackson-core 2.2.0 API)

ノードの探索

public abstract JsonToken nextToken()
    throws IOException, JsonParseException
nextToken - JsonParser (Jackson-core 2.2.0 API)

Tree Model

Tree Modelでは、JSONデータにXML DOMのようにアクセスできます。

  • ツリーの構築 … org.codehaus.jackson.map.ObjectMapper
  • ツリーのノード … org.codehaus.jackson.JsonNode

読み込み

String data = "{\"a\":123,\"b\":true,\"c\":{}}";

ObjectMapper mapper = new ObjectMapper();
try {
    JsonNode rootNode = mapper.readTree(data);

    // 方法1:オブジェクトのフィールドを直接取得
    for (JsonNode node : rootNode) {
        System.out.println(node);
    }

    // 方法2:オブジェクトのフィールド名からフィールドを取得
    Iterator<String> fieldNames = rootNode.fieldNames();
    while (fieldNames.hasNext()) {
        String name = fieldNames.next();
        String value = rootNode.path(name).toString();

        System.out.println(name + ":" + value);
    }

} catch (JsonProcessingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

これを実行すると、

123
true
{}

a:123
b:true
c:{}

のように出力されます。

ノードの探索

ノードの探索には、次の3つのメソッドがあります。基本的に、オブジェクトはその名前を文字列 (String) で指定し、配列はその要素の番号を数値 (int) で指定してアクセスします。

  • path()
  • get()
  • with()
path()
public abstract JsonNode path(String fieldName)
path - JsonNode (jackson-databind 2.2.0 API)
public abstract JsonNode path(int index)
get()

path()に似ていますが、ノードが存在しなかったときにはnullを返します。

public JsonNode get(String fieldName)
get - JsonNode (jackson-databind 2.2.0 API)
public abstract JsonNode get(int index)
with()

path(String)に似ていますが、ノードが存在しなかったときにMissingNodeを返す代わりに、そのノードを生成しオブジェクトに追加します。このメソッドはオブジェクト ノードに対してのみ使用でき、それ以外ではUnsupportedOperationException例外が発生します。

public JsonNode with(String propertyName)
サンプルコード

オブジェクトの場合は、

String data = "{\"a\":123,\"b\":true,\"c\":{}}";

ObjectMapper mapper = new ObjectMapper();
try {
    JsonNode rootNode = mapper.readTree(data);

    JsonNode p1 = rootNode.path("a"); // IntNode
    JsonNode p2 = rootNode.path("b"); // BooleanNode
    JsonNode p3 = rootNode.path("c"); // ObjectNode
    JsonNode p4 = rootNode.path("d"); // MissingNode

    JsonNode g1 = rootNode.get("a"); // IntNode
    JsonNode g2 = rootNode.get("b"); // BooleanNode
    JsonNode g3 = rootNode.get("c"); // ObjectNode
    JsonNode g4 = rootNode.get("d"); // null

//  JsonNode w1 = rootNode.with("a"); // NG : UnsupportedOperationException: Property 'a' has value that is not of type ObjectNode
//  JsonNode w2 = rootNode.with("b"); // NG : UnsupportedOperationException: Property 'b' has value that is not of type ObjectNode
    JsonNode w3 = rootNode.with("c"); // ObjectNode
    JsonNode w4 = rootNode.with("d"); // ObjectNode

} catch (JsonProcessingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

配列の場合は、

String data = "[1,\"ABC\",{}]";

ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(data);

JsonNode p1 = rootNode.path(0); // IntNode
JsonNode p2 = rootNode.path(1); // TextNode
JsonNode p3 = rootNode.path(2); // ObjectNode
JsonNode p4 = rootNode.path(3); // MissingNode

JsonNode g1 = rootNode.get(0); // IntNode
JsonNode g2 = rootNode.get(1); // TextNode
JsonNode g3 = rootNode.get(2); // ObjectNode
JsonNode g4 = rootNode.get(3); // null

Data Binding

Data Bindingでは、JSONデータをJavaのデータ型と相互に変換できます。

  • データの変換 … org.codehaus.jackson.map.ObjectMapper

読み込み

String data = "{\"a\":123,\"b\":true,\"c\":{}}";

ObjectMapper mapper = new ObjectMapper();
try {
    Map<?, ?> rootNode = mapper.readValue(data, Map.class);
    System.out.println(rootNode.get("a")); // 123
    System.out.println(rootNode.get("b")); // true
    System.out.println(rootNode.get("c")); // {}
    System.out.println(rootNode.get("d")); // null

} catch (JsonParseException e) {
    e.printStackTrace();
} catch (JsonMappingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
public <T> T readValue(byte[] src, Class<T> valueType)
    throws IOException, JsonParseException, JsonMappingException
readValue - ObjectMapper (jackson-databind 2.2.0 API)