koda-album

育児プログラマーの日々のざれごと

WindowsストアアプリでJSONデータをパースしてみました

Windowsストアアプリ開発中にJSONデータを解析したいシーンがありましたので、そのときのメモを残しておきます。(もっとスマートな手段あれば教えてください。)

DataContractJsonSerializerクラス

今回は、C#JSONフォーマットのテキストをデシリアライズするクラスを使って、JSON読み込み時に自動でデータ変換する方法を採用しました。 System.Runtime.Serialization.Json名前空間のDataContractJsonSerializerクラスです。

サンプル

というわけで、サンプルです。

private static async System.Threading.Tasks.Task<SampleData> getSampleData(string url)
{
    // JSONデータを取得する
    HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(url);
    HttpWebResponse Response = (HttpWebResponse)await Request.GetResponseAsync();
    Stream stream = Response.GetResponseStream();

    // JSONデータをパースする
    var ser = new DataContractJsonSerializer(typeof(SampleData));
    return ser.ReadObject(stream) as SampleData;
}

引数には、JSONデータ取得するためのURLを指定します。

ちなみに、本題とは関係ないですが、このメソッドにはasync修飾子がついており、そして戻りの型はTaskが指定されてます。 これにより、呼び出し側では、終了を待機しつつ呼び出し側の処理を継続できます。 処理終了を待たずに画面表示したりできるので、ユーザのストレスが軽減されます。 *1

また、DataContractJsonSerializerをnewする時に、変換対象のクラスを渡しています。 それのサンプルも載せておきます。

[DataContract]
public sealed class SampleData
{
    [DataMember(Name = "a")]
    public string aProp { get; private set; }
    [DataMember(Name = "b")]
    public bool bProp { get; private set; }
}

ポイントは、[DataMember]属性を付けることでしょうか。この属性を付けておくことで、それぞれのフィールドに値がマッピングされるようです。

仕組みとしては、JSONデータを読み込むときに、DataMember属性がついている変数のsetterが呼び出される形になるので、なにか自前でデータ加工したい場合は、setter内で実装すればよいはずです。

また、DataMember属性に (Name = "hoge") のようにJSONデータのフィールド名称を指定すると、JSONデータと内部フィールドとのマッピングができます。両者に同じ名前をつければ、(Name = "hoge")は省略してもOKみたいです。

ちなみに、JSONデータのうち使用する項目だけ定義してあげればOKです。

つまづいたところ

DataMember属性を付け忘れるという凡ミスをおかしてて、原因わかるまでちょっと時間くいました。

参考にさせて頂いた記事

ちなみに、 WindowsストアアプリでWindows.Data.Json名前空間のJsonArrayクラスを使ってJSONデータをパースする - 酢ろぐ! で説明されているように、Windows.Data.Json名前空間のJsonArrayクラスやJsonObjectクラスも使えるみたいですが、取り出したデータをうまくデータバインドさせるやり方が分からなかったので、今回はパスしました。

*1:ストアアプリでの非同期プログラミングについては、Windows ストア アプリで重要な非同期プログラミング(C#)について復習 - かずきのBlog@hatenaが詳しいです。