Gsonで変換専用のクラスを作らずにJSONを読み書きする（JSONICの場合のおまけつき）

Gsonは基本的にJSONとJavaオブジェクトを相互に変換するライブラリです。

しかし、変換のための専用クラスを作成しなくてもJSONを読み書きすることができます。

使用頻度が低いJSONや、JSONの中身がかなり不定形でクラスに切り出しにくいなどで、変換のためのクラスを作成したくないときに、使えると思います。

（結論をいえば、結局は基本的に変換専用のPOJOを作った方がよさそうです。どうしても変換専用のクラスを作りたくないなら、JSONICの方が読みやすいコードになるかもしれません）

# JSON編集
下のように配列やネスト構造も作れます。

```json
{
    "outer_name": "outer_value",
    "inner": {
        "inner_name": "inner_value",
        "inner_array": [
            "abc", 
            123, 
            true
        ]
    }
}
```

このJSONを出力するコードは次の通りです。
（上記の例の改行とスペースは見やすさのために加えたものです。実際は改行もスペースもありません）

## `Writer`を使う方法
```java
StringWriter stringWriter = new StringWriter();
JsonWriter gsonWriter = new JsonWriter(new BufferedWriter(stringWriter));
gsonWriter.beginObject();
gsonWriter.name("outer_name").value("outer_value");
gsonWriter.name("inner");
gsonWriter.beginObject();
gsonWriter.name("inner_name").value("string_inner_value");
gsonWriter.name("inner_name").beginArray().value("abc").value("def").value("ghi").endArray();
gsonWriter.endObject();
gsonWriter.endObject();
gsonWriter.close();

String json = new String(stringWriter.getBuffer());
System.out.println(json);

```

参考：[http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonWriter.html](http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonWriter.html)

## `JsonObject`を使う方法
```java
JsonObject root = new JsonObject();
root.addProperty("outer_name", "outer_value");
JsonObject inner = new JsonObject();
inner.addProperty("inner_name", "inner_value");
JsonArray innerArray = new JsonArray();
innerArray.add(new JsonPrimitive("abc"));
innerArray.add(new JsonPrimitive(123));
innerArray.add(new JsonPrimitive(true));
inner.add("inner_array", innerArray);
root.add("inner", inner);

String json2 = new Gson().toJson(root);
System.out.println(json2);
```

# `JSON`読込
## `Reader`を使う方法
茨の道だったので敢えて紹介しません。
[http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html](http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html)が参考になります。

## `JsonObject`を使う方法
編集のところで作成したJSONを読み込んで、一番上の階層の`outer_name`の値を取り出すコードは次のようになります。

```java
JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
String firstElement = jsonObject.get("outer_name").getAsString();
System.out.println(firstElement);
```

`inner_array`の配列の先頭の要素を取り出すコードは次のようになります

```java
JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
JsonObject innter = jsonObject.get("inner").getAsJsonObject();
String firstElement = inner.getAsJsonArray("inner_array").get(0).getAsString();
System.out.println(firstElement);
```


# 感想
## 編集の感想
どちらの方法も、JSONの階層構造がコードの見た目にあまり現れていない点で、読みづらいですね。
特別な理由がない限り、変換専用のオブジェクトを作ろうと思いました。
もしくは上手にラッパークラスを作ればイケるかも、いや、冷静に考えるとあまりやりたくないかな？くらいの実用度だと思います。
## 読込の感想
編集に比べればそこそこマシだと思います。
# GsonではなくJSONICというライブラリなら

```java
StringBuilder stringBuilder = new StringBuilder();
JSONWriter jsonicWriter = new JSON().getWriter(stringBuilder);
jsonicWriter.beginObject();
jsonicWriter.name("outer_name").value("outer_value");
jsonicWriter.name("inner").value(new Object() {
	public String inner_name = "inner_value";
	public Object[] inner_array = { "abc", 123, true };
});
jsonicWriter.endObject();

String json = new String(stringBuilder);
System.out.println(json);
```
という具合にネスト構造を匿名クラスとして表現できて、
さらに、ネストのネストは、匿名クラスの中の匿名クラスで……という調子にオブジェクトの構造でJSONの構造を現せます。
JSONの構造をコードに現しやすいという点ではより優れていると思います。
（まだまだ煩雑ですが……）

JSONICの場合の読み込みはこんな感じです。
Gsonと同じく、ネストの中の配列の先頭の要素を取り出しています。

```java
JSONReader reader = new JSON().getReader(json3);
reader.next();
Map<?, ?> map = reader.getMap();
Map jsonicInner = (Map) map.get("inner");
List array = (List) jsonicInner.get("inner_array");

System.out.println(array.get(0));
```

MapやListになるので、Gsonの場合よりもわかりやすい感じがしますね。

# 結論
* 基本に忠実に、POJO <-> JSON で変換した方がよさげ
* どうしても変換専用のクラスを作りたくないならGsonよりもJSONICの方が可読性が高い気がする