C#でJSON配列のパースに苦労した話

JSONの記法では、Arrayの中に様々な型を含めることができます。

たとえば、
{"result":["str1", "str2", "str3"], "id":1}
{"result":[1, 2, 3, 4], "id":1}
{"result":[{"key":"val"}, {"key":"val2"}], "id":1}
のような単純な配列形式であれば、
C#では次のような簡単な処理でオブジェクトへとデシリアライズできます。
C#
[DataContract]
class StringArray
{
    [DataMember]
    public int id { get; set; }

    [DataMember]
    public string[] result { get; set; }
}

private void deserialize()
{
    var json = "{\"result\":[\"str1\", \"str2\", \"str3\"], \"id\":1}";
    var stream = new MemoryStream(Encoding.Unicode.GetBytes(json));
    var serializer = new DataContractJsonSerializer(typeof(StringArray));
    var obj = (StringArray)serializer.ReadObject(stream);
    Debug.WriteLine("id: " + obj.id);
    foreach(var str in obj.result) {
        Debug.WriteLine("result: " + str);
    }
}
大抵の場合は上記の方法で問題はないのですが、
JSONではArrayの中に含める型が揃っていなければいけないという制限がないため
簡単にはデシリアライズができない構造の場合があり得ます。
{"result":["str1", 2, {"key":"val3"}], "id":1}
普段はJAVA(というかAndroid)でorg.jsonのJSONObjectを使用していたので
デシリアライズなどという概念も特になく、次のように値を取得していました。
JAVA
private void extract() throws JSONException {
    String jsonStr = "{\"result\":[\"str1\", 2, {\"key\":\"val3\"}], \"id\":1}";
    JSONObject json = new JSONObject(jsonStr);
    Log.d(TAG, "id: " + json.getInt("id"));
    JSONArray result = json.getJSONArray("result");
    Log.d(TAG, "result 0th: " + result.getString(0));
    Log.d(TAG, "result 1st: " + result.getInt(1));
    Log.d(TAG, "result 2nd: " + result.getJSONObject(2).getString("key"));
}
C#でJSONのパースの方法を調べているとデシリアライズの方法ばかりヒットして
このようなイレギュラーケースに対応できる方法がなかなか見つからず困っていましたが、
Json.NETのJObjectを使用すればorg.jsonのJSONObjectと同じように手作業で値を取得できるようです。
C#
private void extract()
{
    var json = JObject.Parse("{\"result\":[\"str1\", 2, {\"key\":\"val3\"}], \"id\":1}");
    Debug.WriteLine("id: " + json["id"].ToString());
    var result = json["result"];
    Debug.WriteLine("result 0th: " + result[0].ToString());
    Debug.WriteLine("result 1st: " + result[1].ToString());
    Debug.WriteLine("result 2nd: " + result[2]["key"].ToString());
}
インデクサが使えるのでJavaより少し便利です。

あまり調べても出てこないのは常識だからでしょうか?
それとも使う状況があまり無いからでしょうか?
これでやっと作業が進められます。

終わり。

コメント

このブログの人気の投稿

Lumia 920買った - LTE有効化と開発端末登録

Android で Unicode絵文字入力

Nexus 5 買った