Java API for JSON Processing:JSONの概要
著者:Jitendra Kotamraju
2013年7月公開
JSON(JavaScript Object Notation)は、人間にも機械にも容易に読み書きできる、プログラミング言語に依存しないテキストベースの軽量なデータ交換フォーマットです。JSONでは2つの構造化型(オブジェクトおよび配列)を表現できます。オブジェクトは、順序付けされていない0個以上の名前/値ペアの集合です。配列は、順序付けされた0個以上の値の列です。値として取れるのは、文字列、数字、ブール、null、およびこれら2つの構造化型です。
リスト1は、人物を描写するオブジェクトのJSON表現を示す例としてWikipediaに掲載されているものです。このオブジェクトは、姓と名を表す文字列値、年齢を表す数値、住所を表すオブジェクト値、電話番号オブジェクトを表す配列値で構成されています。
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
リスト1:あるオブジェクトのJSON表現の例
JSONがよく使用されるのはAjaxアプリケーション、構成、データベース、およびRESTful Webサービスです。よく利用されるWebサイトはどれも、それぞれのRESTful WebサービスでJSONをデータ交換フォーマットとして提供しています。
JSON Processing
ava API for JSON Processing(JSR 353)は、オブジェクト・モデルAPIおよびストリーミングAPIを使用してJSONの解析、生成、変換、および問合せを行うための移植可能なAPIです。 オブジェクト・モデルAPIは、JSONデータを表現するランダム・アクセス型のツリー状構造をメモリ内に作成します。作成されたツリーは移動や問合せが可能です。もっとも柔軟なのがこのプログラミング・モデルで、このモデルを使用すると、ツリーのすべてのコンテンツへのランダム・アクセスが必要な処理が可能になります。ただし、このモデルはストリーミング・モデルほど効率的ではなく、より多くのメモリを必要としがちです。 ストリーミングAPIは、JSONをストリーミング方式で解析および生成する手段を提供します。このAPIを使用する場合は、解析および生成をプログラマーが制御できます。ストリーミングAPIにはイベントベースのパーサーがあり、コールバックのイベントを処理する代わりにアプリケーション開発者が次のイベントを要求できます。そのため、JSON Processingに対するさらなる手続き型制御を実現できます。パーサー・イベントの処理または破棄、次のイベントの要求(イベントのプル)をアプリケーション・コードで制御できます。ストリーミング・モデルは、データの他の部分へのランダム・アクセスが必要ないローカル処理に適しています。同様に、ストリーミングAPIを使用する場合は、1度に1つのイベントを記述する方法で、適切なフォーマットのJSONをストリームに生成できます。
オブジェクト・モデルAPI
オブジェクト・モデルAPIはXMLのDocument Object Model(DOM)APIに似ています。JSONのオブジェクト構造および配列構造に不変オブジェクト・モデルを提供する高度なAPIです。これらのJSON構造は、Javaの JsonObject
型とJsonArray
型を使用するオブジェクト・モデルとして表現されます。表1に示すのは、オブジェクト・モデルAPIのおもなクラスとインタフェースです。
JsonObject
は、順序付けされていない0個以上の名前/値ペアの集合にモデルからアクセスするための Map
ビューを提供します。同様に、JsonArray
は、順序付けされた0個以上の値の列にモデルからアクセスするための List
ビューを提供します。
クラスまたはインタフェース | 説明 |
---|---|
Json |
JSONのリーダー、ライター、ビルダー、およびそれらのファクトリ・オブジェクトを作成する静的メソッドが含まれます。 |
JsonGenerator |
1度に1つの値ずつ、JSONデータをストリームに書き込みます。 |
JsonReader |
ストリームからJSONデータを読み取り、オブジェクト・モデルをメモリ内に作成します。 |
|
アプリケーション・コードから値を追加することで、オブジェクト・モデルまたは配列モデルをメモリ内に作成します。 |
JsonWriter |
オブジェクト・モデルをメモリからストリームに書き込みます。 |
|
JSONデータに含まれる値のデータ型を表します。 |
JsonObject、JsonArray、JsonString、
および JsonNumber
は JsonValue
のサブタイプです。これらは、APIでJSON値(null、true、およびfalse)に定義される定数です。
オブジェクト・モデルAPIはビルダー・パターンを使用してこれらのオブジェクト・モデルをゼロから作成します。アプリケーション・コードでは、インタフェース JsonObjectBuilder,
を使用して、JSONオブジェクトを表現するモデルを作成できます。作成されるモデルの型は JsonObject
です。アプリケーション・コードでは、インタフェース JsonArrayBuilder
を使用して、JSON配列を表現するモデルを作成できます。作成されるモデルの型は JsonArray
です。
これらのオブジェクト・モデルも、入力ソース(InputStream
やReader
など)からインタフェースJsonReader
を使用して作成できます。同様に、クラス JsonWriter
を使用してこれらのオブジェクト・モデルを出力ソース(OutputStream
や Writer
など)に書き込むことができます。
たとえば、Facebookの一般投稿を検索するコードを、オブジェクト・モデルAPIを使用して記述するとします。Facebook APIは、リスト2に示すJSONフォーマットで検索結果を返します。
1 {
2 "data" : [
3 { "from" : { "name" : "xxx", ... }, "message" : "yyy", ... },
4 { "from" : { "name" : "ppp", ... }, "message" : "qqq", ... },
5 ...
6 ],
7 ...
8 }
リスト2:Facebookの一般投稿の検索結果を表現するJSON
用語javaに関する一般投稿と投稿者の名前はオブジェクト・モデルAPIを使用して取得できます。リスト3をご覧ください。1~3行目でJsonReaderを作成し、結果を保持するJsonObjectを5行目で作成し、7行目では結果を1つずつループ処理し、8~11行目で投稿者の名前の取得、一般投稿の取得、それらの出力を行っています。JsonReaderおよびこのAPIに含まれる他のオブジェクトは、try-with-resources文(ARM:自動リソース管理とも呼ばれます)で使用できます。
1 URL url = new URL("https://graph.facebook.com/search?q=java&type=post");
2 try (InputStream is = url.openStream();
3 JsonReader rdr = Json.createReader(is)) {
4
5 JsonObject obj = rdr.readObject();
6 JsonArray results = obj.getJsonArray("data");
7 for (JsonObject result : results.getValuesAs(JsonObject.class)) {
8 System.out.print(result.getJsonObject("from").getString("name"));
9 System.out.print(": ");
10 System.out.println(result.getString("message", ""));
11 System.out.println("-----------");
12 }
13 }
リスト3:オブジェクト・モデルAPIを使用したFacebookの投稿の処理
リスト3:オブジェクト・モデルAPIを使用したFacebookの投稿の処理
ストリーミングAPIはXMLのストリーミングAPI(StAX)と似ており、インタフェースJsonParser
とJsonGenerator
で構成されます。JsonParser
には、ストリーミング・モデルを使用してJSONデータを解析するためのメソッドが含まれます。JsonGenerator
には、JSON
データを出力ソースに書き込むためのメソッドが含まれます。表2に示すのは、ストリーミングAPIのおもなクラスとインタフェースです。
クラスまたはインタフェース | 説明 |
---|---|
Json |
JSONのパーサー、ジェネレータ、およびそれらのファクトリ・オブジェクトを作成する静的メソッドが含まれます。. |
JsonParser |
ストリームからJSONデータを読み取ることができるイベントベースのパーサーを表します。 |
JsonGenerator |
1度に1つの値ずつ、JSONデータをストリームに書き込みます。 |
JsonParser
は、プル解析を実行するプログラミング・モデルを使用して、JSONデータに対する読取り専用フォワード・アクセスを提供します。このモデルでは、アプリケーション・コードがスレッドを制御してパーサー・インタフェースのメソッドをコールし、パーサーを前進させるか現行状態のパーサーからJSONデータを取得します。
JsonGenerator
は、JSONデータをストリームに書き込むためのメソッドを提供します。このジェネレータは、名前/値ペアをJSONオブジェクトに書き込むためと、値をJSON配列に書き込むために使用できます。
ストリーミングAPIは、大量のJSONデータを効率的に処理することを目的にした下位レベルのAPIです。他のJSONフレームワーク(JSONバインディングなど)は、このAPIを使用して実装できます。
オブジェクト・モデルAPIを使用して実行した処理(javaに関するFacebookの一般投稿の検索)と同じ処理を、ストリーミングAPIを使用して実行してみましょう。リスト4をご覧ください。1~3行目でストリーミング・パーサーを作成し、4~5行目で次のイベントを取得し、6行目でKEY_NAME
イベントを探し、8~11行目で名前を読み取って出力し、14~16行目で一般投稿を読み取って出力しています。ストリーミングAPIを使用すると、オブジェクト・モデルAPIを使用して同じ処理を実行する場合と比較して効率的に名前と一般投稿にアクセスできます。
1 URL url = new URL("https://graph.facebook.com/search?q=java&type=post");
2 try (InputStream is = url.openStream();
3 JsonParser parser = Json.createParser(is)) {
4 while (parser.hasNext()) {
5 Event e = parser.next();
6 if (e == Event.KEY_NAME) {
7 switch (parser.getString()) {
8 case "name":
9 parser.next();
10 System.out.print(parser.getString());
11 System.out.print(": ");
12 break;
13 case "message":
14 parser.next();
15 System.out.println(parser.getString());
16 System.out.println("---------");
17 break;
18 }
19 }
20 }
21 }
リスト4:ストリーミングAPIを使用したFacebook投稿の処理
まとめ
Java API for JSON Processingは次の機能を提供します。
- 入力ストリームを解析して不変オブジェクトまたはイベント・ストリームを生成する
- イベント・ストリームまたは不変オブジェクトを出力ストリームに書き込む
- 不変オブジェクトをプログラムを使用して切り替える
- ビルダーを使用して不変オブジェクトをプログラムで構築する
APIはデータ・バインディングの構築、変換、問合せ、その他のAPI操作を実行するためのベースになります。JAX-RS 2.0ではJava API for JSON Processingがネイティブに統合されます。
関連項目
著者について
Jitendra Kotamrajuはオラクルの技術スタッフの主要メンバーであり、JSON Processingの仕様策定を指揮しています。また、GlassFishを支える重要なエンジニアの一人です。JSON Processingプロジェクトのリーダーに就任する前は、JAX-WS 2.2の仕様策定と実装に携わっていました。
議論への参加
Facebook、Twitter、オラクルのJava関連ブログでJavaコミュニティの議論にご参加ください。