JSONはXMLよりコンパクトでシンプルな構文で扱いやすいです。アンドロイドアプリでサーバとやりとりするときはJSONを利用することが多いです。
Android SDKにもJSONライブラリはありますが、JsonPullParserはサイズが小さく高速です。そして、APT(Annotation Processing Tool)を利用してアノテーションでJSONとPOJO(Plain Old Java Object)をマッピングするという特徴があります。
またXmlPullParserと同様に、全体を読み終わるまで待つのではなく、読み終わったJSONオブジェクトインスタンスを次々と受け取ることができます。
ダウンロード
ダウンロードは作者の@vvakameさんのgithubからダウンロードできます。
JsonPullParserはJSONからPOJOに変換してくれるユーティリティクラスを自動生成します。アノテーションを書くことが取っつきにくいかもしれませんが、なれれば、とっても簡単です。
今回は現時点で最新のjsonpullparser-1.4.zipをダウンロードしました。このzipファイルはソースコード含む4つのzipファイルが含まれており、利用するのは、以下の二つのjarファイルです。
- jsonpullparser-apt-1.4.jar – コード生成時に必要なもの
- jsonpullparser-core-1.4.jar – 実行時に利用するもの
- JsonPullParserClassPostfix – 自動生成するクラスの接尾語
- JsonPullParserDebug – デバッグ出力の有無
プロジェクトのlibsに入れるのは、jsonpullparser-core-1.4.jarだけで、jsonpullparser-apt-1.4.jarはEclipseのannotation Factoryのパスで指定します。
では、その設定を行っていきましょう。
Elipseでの設定
jsonpullparser-core-1.4.jarは、プロジェクトのlibsフォルダにDrag&Dropでコピーします。jsonpullparser-apt-1.4.jarは、c:\libs(好きな場所へ)に置いておきます。
次にEclipseのプロジェクトプロパティからJava Complier->Annotation Processingを選択すると以下のような画面になります。
ここで、Enable project specific settingsにチェックします。Generated source directoryは自動生成したJavaソースコードをどこに保存するかを指定します。アンドロイドなら、./genとしておくとよいでしょう。そして、Processor optionsに以下のものを追加します。
JsonPullParserClassPostfixは好きな語を指定します。私はGenとしています。JsonPullParserDebugはtrueとしておきます。
次にAnnotation Processing->Factory Pathを選択します。ここで、先ほどのもう一つのライブラリを指定します。まず、Enable project specific settingsをチェックします。そして、Add External JARS…をクリックして、jsonpullparser-apt-1.4.jarを追加します。
POJOを作成
以下のようなJSONを読み込むことを想定します。
{ "id" : "1", "name" : "hoge", "version_code" : "1" }
このJSONに対するPOJOを作成します。クラス宣言にJsonModelアノテーションを付加します。そして、JSONの各変数にひもづくメンバ変数にはJsonKeyアノテーションをつけます。
さらにそれらのsetter,getterを追加します。
この状態でビルドすると、genディレクトリ下にMyJsonGen.javaが生成されているはずです。されていなければ、一度クリーンを実行して、手動ビルドを実行してください。それでも生成されなければ再度Elipseの設定を見直してください。
MyJson.java
package com.example.jsonpullparser; import net.vvakame.util.jsonpullparser.annotation.JsonKey; import net.vvakame.util.jsonpullparser.annotation.JsonModel; // decamelize=true : xxx_yyy -> xxxYyyへ変換します。 @JsonModel(decamelize=true) public class MyJson { @JsonKey private String id; @JsonKey private String name; // キャメルスタイルのメンバ変数の例 // @JsonModel(decamelize=true) // またはメンバごとに @JsonKey("version_code")と書くこともできます。 @JsonKey private String versionCode; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersionCode() { return versionCode; } public void setVersionCode(String versionCode) { this.versionCode = versionCode; } }
JSONをパースする
では、実際にJSONをパースして、POJOを生成するところをみてみましょう。
public class MainActivity extends Activity { static final String TAG = MainActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyJsonDownloadTask().execute(); } class MyJsonDownloadTask extends AsyncTask<Void, MyJson, Void> { @Override protected Void doInBackground(Void... params) { try { URL url = new URL("http://www.notice.co.jp/paads/myjson.json"); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); try { InputStream in = new BufferedInputStream(conn.getInputStream()); JsonPullParser parser = JsonPullParser.newParser(in); MyJson json = MyJsonGen.get(parser); Log.d(TAG, "id = " + json.getId()); Log.d(TAG, "name = " + json.getName()); Log.d(TAG, "versionCode = " + json.getVersionCode()); } finally { conn.disconnect(); } } catch (JsonFormatException e) { Log.e(TAG, "doInBackground", e); } catch (IOException e) { Log.e(TAG, "doInBackground", e); } return null; } } }
一応、HTTPでJSONを取得するようにしてみました。今回は単体のJSONでしたが、getList()を利用すれば配列も取得できます。皆さんも是非利用してみてください。