LoginSignup
13
12

More than 5 years have passed since last update.

JSONObject を Bundle に変換する

Last updated at Posted at 2015-07-02

JSON をパースして詰め替えるのが面倒

Android アプリ開発において Bundle が非常に便利な入れ物であることは 拙記事: Bundle で述べた。
RecyclerView / ListView の Adapter に詰めるのも Intent の引数に渡すにも Bundle を使う。

一方 WebAPI を用いた開発だと JSON を受け取るタイプの API をコールしてアプリ側で JSON をパースして使いやすいように詰め替える処理を書く事が多い。それが面倒なので GSONJackson といった JSON パーサライブラリを用いることもあるだろう。だがこれらのライブラリは自前の JavaBeans 若しくは POJO を用意する事が前提になっている。JSON をパースしてくれるのは有難いがこの POJO を毎回用意するのが面倒だ。Bundle に直接詰め替えたい。

一発で変換可能なユーティリティメソッド

というわけで JSONObject を簡単に Bundle に変換する為のメソッドを書いてみた。JSONObject 内に JSONArray 若しくは JSONObject が存在する場合も再帰的に解釈する。{"hoge": "fuga", "list": [{"a": 1}, {"b": 2}], "json": {"hoge": "fuga"}} 的なものも OK ということ。JSONArray は ArrayList<Bundle> に変換されるので Bundle#getParcelableArrayList() で取って欲しい。

class Utils {

    /**
     * JSONObject を Bundle に適切に変換して返す.
     * JSONArray は ArrayList<Bundle> に変換される.
     *
     * @param json JSONObject
     * @return Bundle
     */
    public static Bundle toBundle(final JSONObject json) {
        final Bundle bundle = new Bundle();
        final Iterator<String> iterator = json.keys();
        while (iterator.hasNext()) {
            final String key = iterator.next();
            if (json.isNull(key)) {
                bundle.putString(key, null);
                continue;
            }
            final Object value = json.opt(key);
            if (value instanceof JSONObject) {
                bundle.putBundle(key, toBundle((JSONObject) value));
            } else if (value instanceof JSONArray) {
                bundle.putParcelableArrayList(key, toBundle((JSONArray) value));
            } else if (value instanceof Boolean) {
                bundle.putBoolean(key, (boolean) value);
            } else if (value instanceof String) {
                bundle.putString(key, (String) value);
            } else if (value instanceof Integer) {
                bundle.putInt(key, (int) value);
            } else if (value instanceof Long) {
                bundle.putLong(key, (long) value);
            } else if (value instanceof Double) {
                bundle.putDouble(key, (double) value);
            }
        }
        return bundle;
    }

    /**
     * JSONArray を ArrayList<Bundle> に適切に変換して返す.
     *
     * @param array JSONArray
     * @return ArrayList<Bundle>
     */
    public static ArrayList<Bundle> toBundle(final JSONArray array) {
        final ArrayList<Bundle> bundles = new ArrayList<>();
        for (int i = 0, size = array.length(); i < size; i++) {
            bundles.add(toBundle(array.optJSONObject(i)));
        }
        return bundles;
    }
}

以下のような感じで一発でパースできる。Volley 等の HTTP リクエスト用のライブラリを使用しているなら Request<Bundle> 等と戻り値を Bundle にして中で JSONObject から Bundle にパースして UI 側で最初から Bundle で扱うとコードが短くなる。

final JSONObject json;
try {
    json = new JSONObject("{\"hoge\": \"fuga\", \"hage\": null, \"long\": 9223372036854775808, \"double\": 2.4d, \"list\": [{\"a\": 1}, {\"b\": 2}]}");
} catch (JSONException e) {
    throw new AndroidRuntimeException(e);
}
Log.d("BUNDLE", Utils.toBundle(json).toString());
D/BUNDLE(30128): Bundle[{double=2.4, hage=null, hoge=fuga, list=[Bundle[{a=1}], Bundle[{b=2}]], long=9.223372036854776E18}]
13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12