JSONファイルパーサparsonでJSONを成型する方法

#はじめに
JSONパーサの[parson](http://kgabis.github.com/parson/)が便利だったのでまとめておきます。今回はJSONの読み込みではなく成型に絞った内容です。JSONって何？という方は[こちら](https://qiita.com/chihiro/items/dd1912c1406dbfe16b72)。

#最も単純な例
細かい話は後回しにして、単純な例を見てみましょう。

```c:tutorial.c
	JSON_Value* test_val = json_value_init_object(); // オブジェクトと紐づくよう初期化
	JSON_Object* test_obj = json_value_get_object(test_val); // 紐づける

	// メンバをセット
	json_object_set_string(test_obj, "key_str", "example");
	json_object_set_number(test_obj, "key_num", 1.0);
	json_object_set_boolean(test_obj, "key_bool", true);

	// 何かしらの処理

	// 最後に解放処理
	json_value_free(test_val);
```

結果は以下の通りです。

```json
{
    "key_str": "example",
    "key_num": 1,
    "key_bool": true
}
```

一番ややこしいのは、JSON_ValueとJSON_Objectの２つが存在するところです。
JSON_Valueについては後で説明するので一旦保留にしておきます。
一方、JSON_Objectとは、中カッコで囲まれ、中にいくつかメンバを持つもので、単にオブジェクトと呼んでいるものです（まさに上に表示されているもの）。

#JSON_Valueとは？
[こちら](https://qiita.com/chihiro/items/dd1912c1406dbfe16b72)でも紹介されているように、バリューとして取り得る型には６つの種類があります。JSON_Valueとは、その６種類のどれとでも紐づくことができる、より上位の存在です。

上の例では、

 - バリューを「あなたはオブジェクトと紐づくんですよ」と初期化
 - 実際にオブジェクトと紐づける
 - オブジェクトの方にメンバをセットしていく

という流れになっています。

上の例だけを見ていると、「JSON_Valueなんていらないのでは？」と思ってしまうかもしれませんが、これが後々になって生きてきます。

#もっと複雑なJSONを作りたい！
上記の例では、バリューの型としてそれぞれ文字列・数値・booleanの３つをセットできました。基本はこれで押さえているのですが、先ほど作ったJSONを、下のようにさらに入れ子にするにはどうすればいいでしょうか？

```json
{
    "key_obj": {
        "key_str": "example",
        "key_num": 1,
        "key_bool": true
    }
}
```

てっきりjson_object_set_object()のような関数があるかと思いきや、実は、文字列や数値の場合とは異なり、**オブジェクトを直接セットする関数はない**んです。私はここで詰まりました。

#間接的にオブジェクトをセットする
JSON_Objectは直接セットできません。その代わりに、JSON_Valueをセットする関数json_object_set_value()が用意されています。この関数を使って入れ子にしたコードがこちら。

```c:object.c
	// 親となるオブジェクトを作成
	JSON_Value* root_val = json_value_init_object();
	JSON_Object* root_obj = json_value_get_object(root_val);

	// 入れ子になるオブジェクトを作成
	JSON_Value* test_val = json_value_init_object();
	JSON_Object* test_obj = json_value_get_object(test_val);

	json_object_set_string(test_obj, "key_str", "example");
	json_object_set_number(test_obj, "key_num", 1.0);
	json_object_set_boolean(test_obj, "key_bool", true);

	// 親オブジェクトにメンバをセット
	json_object_set_value(root_obj, "key_obj", test_val);

	// 何かしらの処理

	// 最後に親のみ解放
	json_value_free(root_val);
```

繰り返しになりますが、結果は以下の通りです。

```json
{
    "key_obj": {
        "key_str": "example",
        "key_num": 1,
        "key_bool": true
    }
}
```

さらに外側に親となるJSON_Objectを作り、json_object_set_value()を呼ぶのがミソです。
ちなみに、最後の解放処理は、どれだけ入れ子になっても最上位さえ解放すればOKです。

#間接的に配列をセットする
オブジェクトと同じようにして配列もセットすることができます。
オブジェクトの場合と流れは同じですが、初期化や要素の追加方法が若干異なります。

```c:array.c
	// 親となるオブジェクトを作成
	JSON_Value* root_val = json_value_init_object();
	JSON_Object* root_obj = json_value_get_object(root_val);

	// 配列を作成
	JSON_Value* test_val = json_value_init_array();
	JSON_Array* test_arr = json_value_get_array(test_val);

	json_array_append_string(test_arr, "example1");
	json_array_append_string(test_arr, "example2");

	// 親オブジェクトにメンバをセット
	json_object_set_value(root_obj, "key_arr", test_val);

	// 何かしらの処理

	// 最後に親のみ解放
	json_value_free(root_val);
```

結果は以下の通りです。

```json
{
    "key_arr": [
        "example1",
        "example2"
    ]
}
```

#まとめ
以上のコードを流用すれば、入れ子式に複雑なJSONも成型することができるはずです。
もっと効率のいい方法は、[こちらのSerialization](http://kgabis.github.com/parson/)を参考にどうぞ。dotset系の関数を使うともっとシンプルにできます。