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が詳しいです。