10 Java API for JSON Processing
この章の内容は次のとおりです。
JSONの概念についてさらに学習するには、Java EE 7チュートリアル(http://docs.oracle.com/javaee/7/tutorial/jsonp.htm
)の「JSON Processing」の章を参照してください。
- JavaScript Object Notation (JSON)について
JSONは軽量なデータ交換形式で、インターネット経由で相互通信するアプリケーションのデータのシリアライズおよびデシリアライズ用の一般的な形式として、広く使用されています。このようなアプリケーションは、異なるプログラミング言語で作成され、まったく異なる環境で実行されることがよくあります。 - オブジェクト・モデルAPI
オブジェクト・モデルAPIは、JSONオブジェクトおよび配列構造の不変のオブジェクト・モデルを提供する高レベルなAPIです。 - ストリーミングAPI
ストリーミングAPIは、大量のJSONデータを効率的に処理できるように設計された、低レベルのAPIです。
JavaScript Object Notation (JSON)について
JSONは軽量なデータ交換形式で、インターネット経由で相互通信するアプリケーションのデータのシリアライズおよびデシリアライズ用の一般的な形式として、広く使用されています。このようなアプリケーションは、異なるプログラミング言語で作成され、まったく異なる環境で実行されることがよくあります。
JSONはオープンな標準であり、読取りと書込みが簡単で、他の表現よりコンパクトなため、このような使用例に適しています。RESTful Webサービスでは通常、リクエストとレスポンス内のデータの形式としてJSONが広く利用されており、JSONには終了タグがないため、JSON表現は対応するXML表現よりも通常はコンパクトです。
Java API for JSON Processingは、JSONテキストの処理(解析、生成、変換、問合せ)に便利です。JSONデータの生成および解析用に、XMLドキュメントで使用されるものと同じような2つのプログラミング・モデルが用意されています。
-
オブジェクト・モデルでは、メモリー内のJSONデータを示すツリーが作成されます。このツリーは参照と分析が可能です。メモリー内で生成されたJSONデータは不変であり、変更できませんが、オブジェクト・モデルは非常に柔軟で、ツリーのすべてのコンテンツにアクセスする必要がある処理に使用できます。ただし、通常はストリーミング・モデルより低速で、より多くのメモリーが必要です。このオブジェクト・モデルでは、ツリー全体を瞬時に参照して、JSON出力が生成されます。
オブジェクト・モデルの使用方法の詳細は、「オブジェクト・モデルAPI」を参照してください。
-
ストリーミング・モデルでは、JSONデータの要素を一度に1つずつ読み取るイベント・ベースのパーサーを使用します。パーサーによってイベントが生成され、オブジェクトや配列の開始または終了時、キーや値の検出時には処理が停止されます。各要素はアプリケーション・コードごとに処理または破棄することができ、パーサーは次のイベントに進みます。このアプローチは、要素の処理に残りのデータからの情報が不要なローカル処理に適しています。ストリーミング・モデルでは、一度に1つの要素を使う関数コールにより、所定のストリームにJSON出力が生成されます。
ストリーミング・モデルの使用方法の詳細は、「ストリーミングAPI」を参照してください。
親トピック: Java API for JSON Processing
オブジェクト・モデルAPI
オブジェクト・モデルAPIは、JSONオブジェクトおよび配列構造の不変のオブジェクト・モデルを提供する高レベルなAPIです。
これらのJSON構造は、JavaのJsonObject
型およびJsonArray
型を使用するオブジェクト・モデルとして表現されます。インタフェースjavax.json.JsonObject
にはマップ・ビューがあり、ゼロ(0)個以上の名前/値ペアの、順不同のコレクションにモデルからアクセスできます。同様に、javax.json.JsonArray
インタフェースにはリスト・ビューがあり、ゼロ(0)個以上の連続した値にモデルからアクセスできます。
オブジェクト・モデルAPIでは、ビルダー・パターンを使用してこれらのオブジェクト・モデルを作成します。javax.json.JsonObjectBuilder
およびjavax.json.JsonArrayBuilder
インタフェースには、それぞれJsonObject
型およびJsonArray
型のモデルを作成するメソッドがあります。
これらのオブジェクト・モデルは、javax.json.JsonReader
インタフェースを使用して入力ソースから作成することもできます。同様に、これらのオブジェクト・モデルは、javax.jsonJsonWriter
インタフェースを使用して出力ソースに書き込むことができます。
次の各項では、オブジェクト・モデルAPIの使用例を示します。
親トピック: Java API for JSON Processing
JSONデータからのオブジェクト・モデルの作成
次の例では、テキスト・ファイル内のJSONデータからオブジェクト・モデルを作成する方法を示します。
import java.io.FileReader; import javax.json.Json; import javax.json.JsonReader; import javax.json.JsonStructure; ... JsonReader reader = Json.createReader(new FileReader("jsondata.txt")); JsonStructure jsonst = reader.read();
オブジェクト参照jsonst
は、ファイルの内容に応じてJsonObject
型またはJsonArray
型のいずれかになります。JsonObject
およびJsonArray
はJsonStructure
のサブタイプです。この参照はツリーの最上位を表したもので、ツリーの参照に使用したり、ストリームにJSONデータとして書き込むことができます。
親トピック: オブジェクト・モデルAPI
アプリケーション・コードからのオブジェクト・モデルの作成
次の例では、アプリケーション・コードからオブジェクト・モデルを作成する方法を示します。
import javax.json.Json; import javax.json.JsonObject; ... JsonObject model = Json.createObjectBuilder() .add("firstName", "Duke") .add("lastName", "Java") .add("age", 18) .add("streetAddress", "100 Internet Dr") .add("city", "JavaTown") .add("state", "JA") .add("postalCode", "12345") .add("phoneNumbers", Json.createArrayBuilder() .add(Json.createObjectBuilder() .add("type", "mobile") .add("number", "111-111-1111")) .add(Json.createObjectBuilder() .add("type", "home") .add("number", "222-222-2222"))) .build();
オブジェクト参照モデルはツリーの最上位を表したもので、add
メソッドの呼出しをネストして作成し、build
メソッドを呼び出してビルドします。javax.json.JsonObjectBuilder
インタフェースには、次のadd
メソッドが含まれています。
JsonObjectBuilder add(String name, BigDecimal value) JsonObjectBuilder add(String name, BigInteger value) JsonObjectBuilder add(String name, boolean value) JsonObjectBuilder add(String name, double value) JsonObjectBuilder add(String name, int value) JsonObjectBuilder add(String name, JsonArrayBuilder builder) JsonObjectBuilder add(String name, JsonObjectBuilder builder) JsonObjectBuilder add(String name, JsonValue value) JsonObjectBuilder add(String name, long value) JsonObjectBuilder add(String name, String value) JsonObjectBuilder addNull(String name)
javax.json.JsonArrayBuilder
インタフェースにも同様のadd
メソッドが含まれていますが、name (key)パラメータは使用できません。配列およびオブジェクトをネストするには、この例で示したように、JsonArrayBuilder
の新規オブジェクトまたはJsonObjectBuilder
の新規オブジェクトを対応するadd
メソッドに渡します。
生成されるツリーは、JSON構文で表したJSONデータです。
親トピック: オブジェクト・モデルAPI
オブジェクト・モデルの参照
次の例では、オブジェクト・モデルを参照する簡単な方法を示します。
import javax.json.JsonValue; import javax.json.JsonObject; import javax.json.JsonArray; import javax.json.JsonNumber; import javax.json.JsonString; ... public static void navigateTree(JsonValue tree, String key) { if (key != null) System.out.print("Key " + key + ": "); switch(tree.getValueType()) { case OBJECT: System.out.println("OBJECT"); JsonObject object = (JsonObject) tree; for (String name : object.keySet()) navigateTree(object.get(name), name); break; case ARRAY: System.out.println("ARRAY"); JsonArray array = (JsonArray) tree; for (JsonValue val : array) navigateTree(val, null); break; case STRING: JsonString st = (JsonString) tree; System.out.println("STRING " + st.getString()); break; case NUMBER: JsonNumber num = (JsonNumber) tree; System.out.println("NUMBER " + num.toString()); break; case TRUE: case FALSE: case NULL: System.out.println(tree.getValueType().toString()); break; } }
navigateTree
メソッドは、「JSONデータからのオブジェクト・モデルの作成」および「アプリケーション・コードからのオブジェクト・モデルの作成」で示したモデルで使用できます。
navigateTree(model, null);
navigateTree
メソッドは2つの引数(JSON要素とキー)を取ります。キーは、オブジェクト内のキー/値のペアを出力する場合にのみ使用します。ツリー内の要素は、JsonValue
型で表します。要素がオブジェクトまたは配列の場合、オブジェクトまたは配列に格納されている各要素に対して、このメソッドの新規呼出しが行われます。要素が値の場合は、標準出力に表示されます。
JsonValue.getValueType
メソッドは、要素がオブジェクト、配列または値のいずれであるかを識別します。オブジェクトの場合、JsonObject.keySet
メソッドはオブジェクトのキーが含まれる文字列セットを返し、JsonObject.get(String name)
メソッドはキーがname
である要素の値を返します。配列の場合は、JsonArray
にList<JsonValue>
インタフェースが実装されます。この例で示したように、JsonObject.keySet
によって返されたSet<String>
インスタンス、およびJsonArray
のインスタンスには拡張for
ループを使用できます。
「アプリケーション・コードからのオブジェクト・モデルの作成」で示したモデルでnavigateTree
メソッドを実行すると、次の出力が生成されます。
OBJECT Key firstName: STRING Duke Key lastName: STRING Java Key age: NUMBER 18 Key streetAddress: STRING 100 Internet Dr Key city: STRING JavaTown Key state: STRING JA Key postalCode: STRING 12345 Key phoneNumbers: ARRAY OBJECT Key type: STRING mobile Key number: STRING 111-111-1111 OBJECT Key type: STRING home Key number: STRING 222-222-2222
親トピック: オブジェクト・モデルAPI
ストリームへのオブジェクト・モデルの書込み
「JSONデータからのオブジェクト・モデルの作成」および「アプリケーション・コードからのオブジェクト・モデルの作成」で作成したオブジェクト・モデルは、次に示すように、javax.json.JsonWriter
インタフェースを使用してストリームに書き込むことができます。
import java.io.StringWriter; import javax.json.JsonWriter; ... StringWriter stWriter = new StringWriter(); JsonWriter jsonWriter = Json.createWriter(stWriter); jsonWriter.writeObject(model); jsonWriter.close(); String jsonData = stWriter.toString(); System.out.println(jsonData); The Json.createWriter method takes an output stream as a parameter. The JsonWriter.writeObject method writes the object to the stream. The JsonWriter.close method closes the underlying output stream. The following example uses try-with-resources to close the JSON writer automatically: StringWriter stWriter = new StringWriter(); try (JsonWriter jsonWriter = Json.createWriter(stWriter)) { jsonWriter.writeObject(model); } String jsonData = stWriter.toString(); System.out.println(jsonData);
親トピック: オブジェクト・モデルAPI
ストリーミングAPI
ストリーミングAPIは、大量のJSONデータを効率的に処理できるように設計された、低レベルのAPIです。
このAPIは次のインタフェースで構成されます。
インタフェース | 説明 |
---|---|
javax.json.stream.JsonParser |
JSONをストリーミングで解析するメソッドが含まれます。 このインタフェースでは、プル解析プログラミング・モデルを使用して、JSONデータに対し前方/読取り専用アクセスを行うことができます。このモデルでは、アプリケーション・コードを使用して、パーサー・インタフェースでスレッドの制御やメソッドのコールを行い、パーサーを前方に移動したり、現在のパーサーの状態からJSONデータを取得したりできます。 |
javax.json.stream.JsonGenerator |
JSONをストリーミングで出力ソースに書き込むメソッドが含まれます。 このインタフェースには、JSONを出力ソースに書き込むメソッドがあります。ジェネレータによって、名前/値ペアがJSONオブジェクトに、値がJSON配列に書き込まれます。 |
次の各項では、ストリーミングAPIの使用例を示します。
パーサーを使用したJSONデータの読取り
ストリーミングAPIは、JSONテキストを解析する上で、最も効率的な方法です。次の例では、JsonParser
オブジェクトの作成方法およびイベントを使用してJSONデータを解析する方法を示します。
import javax.json.Json; import javax.json.stream.JsonParser; ... JsonParser parser = Json.createParser(new StringReader(jsonData)); while (parser.hasNext()) { JsonParser.Event event = parser.next(); switch(event) { case START_ARRAY: case END_ARRAY: case START_OBJECT: case END_OBJECT: case VALUE_FALSE: case VALUE_NULL: case VALUE_TRUE: System.out.println(event.toString()); break; case KEY_NAME: System.out.print(event.toString() + " " + parser.getString() + " - "); break; case VALUE_STRING: case VALUE_NUMBER: System.out.println(event.toString() + " " + parser.getString()); break; } }
この例は、次の3つのステップで構成されます。
Json.createParser
静的メソッドを呼び出して、パーサー・インスタンスを取得します。JsonParser.hasNext
メソッドおよびJsonParser.next
メソッドを使用して、パーサー・イベントを繰り返します。- 要素ごとにローカル処理を実行します。
この例は、パーサーから生成される可能性のある10個のイベント・タイプを示しています。パーサーのnext
メソッドで次のイベントに進みます。
KEY_NAME
、VALUE_STRING
およびVALUE_NUMBER
の各イベント・タイプでは、JsonParser.getString
メソッドを呼び出して、要素の内容を取得できます。
VALUE_NUMBER
イベントでは、次のメソッドを使用することもできます。
START_OBJECT KEY_NAME firstName - VALUE_STRING Duke KEY_NAME lastName - VALUE_STRING Java KEY_NAME age - VALUE_NUMBER 18 KEY_NAME streetAddress - VALUE_STRING 100 Internet Dr KEY_NAME city - VALUE_STRING JavaTown KEY_NAME state - VALUE_STRING JA KEY_NAME postalCode - VALUE_STRING 12345 KEY_NAME phoneNumbers - START_ARRAY START_OBJECT KEY_NAME type - VALUE_STRING mobile KEY_NAME number - VALUE_STRING 111-111-1111 END_OBJECT START_OBJECT KEY_NAME type - VALUE_STRING home KEY_NAME number - VALUE_STRING 222-222-2222 END_OBJECT END_ARRAY END_OBJECT
親トピック: ストリーミングAPI
ジェネレータを使用したJSONデータの書込み
次の例では、ストリーミングAPIを使用してJSONデータをファイルに書き込む方法を示します。
FileWriter writer = new FileWriter("test.txt"); JsonGenerator gen = Json.createGenerator(writer); gen.writeStartObject() .write("firstName", "Duke") .write("lastName", "Java") .write("age", 18) .write("streetAddress", "100 Internet Dr") .write("city", "JavaTown") .write("state", "JA") .write("postalCode", "12345") .writeStartArray("phoneNumbers") .writeStartObject() .write("type", "mobile") .write("number", "111-111-1111") .writeEnd() .writeStartObject() .write("type", "home") .write("number", "222-222-2222") .writeEnd() .writeEnd() .writeEnd(); gen.close();
この例では、ライター・ストリームまたは出力ストリームをパラメータとして取るJson.createGenerator
静的メソッドを呼び出して、JSONジェネレータを取得します。例では、write
、writeStartArray
、writeStartObject
およびwriteEnd
の各メソッドの呼出しをネストして、JSONデータをtest.txt
ファイルに書き込みます。JsonGenerator.close
メソッドで、内部のライター・ストリームまたは出力ストリームを閉じます。
親トピック: ストリーミングAPI