.NET標準のDataContractJsonSerializerでのJSON処理
それでは、以下のようなJSONデータについて、最初にDataContractJsonSerializerでの読み書きの方法を見ていきましょう。このJSONデータは友人情報を表しており、文字列データとしてNameとAddress、数値としてAgeというフィールドを含んでいます。
{ "Name":"Doi", "Address":"Tokyo", "Age":32 }
なお、以降のコードは、配布サンプルのDataContractJsonSerializerSampleプロジェクトに含まれています。
参照設定
まず、DataContractJsonSerializerを使用するための設定を行いましょう。DataContractJsonSerializerはSystem.Runtime.Serializationというコンポーネントに含まれるクラスです。このクラスは、Visual Studioのプロジェクトの作成の際に、WCFに関連するテンプレートを選択した場合などは、そのまま使用できますが、[コンソール アプリケーション]などのテンプレートでは参照設定を行う必要があります。
Visual Studioの[プロジェクト]メニューから[参照の追加]を選択し、[.NET]タブから以下のように、System.Runtime.Serializationコンポーネントを選択して[OK]ボタンを押します。
また、必要なusingステートメントをファイル先頭で以下のように宣言しておきます。
using System.Runtime.Serialization; using System.Runtime.Serialization.Json;
.NETクラスの定義
DataContractJsonSerializerは、JSONを読み書きするためのライブラリというよりは、あくまでも.NETのクラスとJSONデータの相互変換を目的として準備されたライブラリです。そのため、JSONデータを扱う際には、JSONデータの構造に対応する.NETのクラスをあらかじめ定義しておく必要があります。先ほどのJSONデータに対応する.NETのクラスの定義は以下のようになります。
[DataContract] public class FriendInfo { [DataMember] public string Name{get;set;} [DataMember] public string Address { get; set; } [DataMember] public int Age { get; set; } }
ここでは、JSONデータのフィールドと同じ名前のName, Address, Ageプロパティを定義しています。なお、注意しなければならないのは、対象とするクラスにはDataContract属性を、プロパティにはDataMember属性を、それぞれ指定する必要がある点です。これらの属性はWCFでクラスを公開するために必要な属性で、データ・コントラクトと呼ばれます。データ・コントラクトの詳細については以下の記事を参照してください。
JSONデータの読み書き
.NETクラスの定義ができれば、JSONデータの読み書きは簡単です。
まずはJSONデータの読み込みを行ってみましょう。
//(1)読み込むJSONデータ var jsonString = @"{""Address"":""Tokyo"",""Age"":32,""Name"":""Doi""}"; //(2)DataContractJsonSerializerをインスタンス化 var serializer = new DataContractJsonSerializer(typeof(FriendInfo)); //(3)JSONデータを文字列からバイト配列に変換 var jsonBytes = Encoding.Unicode.GetBytes(jsonString); //(4)バイト配列を読み込むMemoryStreamクラスを定義 var sr = new MemoryStream(jsonBytes); //(5)ReadObjectメソッドでJSONデータを.NETオブジェクトに変換 var obj = (FriendInfo)serializer.ReadObject(sr); //(6)変換したオブジェクトのプロパティ内容を確認 Console.WriteLine("Name:{0}, Address:{1}, Age:{2}", obj.Name,obj.Address,obj.Age);
実際にデータを読み込むのはDataContractJsonSerializerクラスのReadObjectというメソッドですが、このメソッドを使用するにはいくつかの前準備が必要になるので、順を追って見ていきましょう。
(1)は読み込むJSONデータです。今回は文字列として定義していますが、もちろんWebサービスから取得したデータなどでも構いません。
(2)では、DataContractJsonSerializerをインスタンス化しています。この際、変換対象とする型(今回はFriendInfoクラス)を引数に指定するのがポイントです。これにより、このインスタンスはJSONデータとFriendInfoオブジェクトの相互変換を行うように設定されます。
(3)、(4)では、JSONデータの文字列をいったんバイト配列に変換した上で、それを読み込むMemoryStreamクラスを作成しています。これは、DataContractJsonSerializerがJSONデータを文字列としてではなく、Stream(.NETにおいて、ファイルや通信など連続するバイト列を表すクラス)として扱う仕様となっているためです。JSONデータを文字列として読み書きできないのはやや使いづらいですが、「.NETのクラスをJSONデータのWebサービスとして公開する」というDataContractJsonSerializerの本来の用途から考えると、こういった仕様になっているのは仕方ないところです。
(5)では、DataContractJsonSerializerのReadObjectメソッドを使い、StreamからJSONデータを読み取り、.NETオブジェクトに変換しています。ReadObjectメソッドの返値はObject型なので、ここではFriendInfo型にキャストしています。
(6)では、JSONデータから変換したFriendInfoオブジェクトの内容を確認しています。出力結果は以下のようになります。
Name:Doi, Address:Tokyo, Age:32
(1)で定義したJSONデータがきちんと.NETのオブジェクトに変換されていることが分かります。
一方、JSONデータの書き込みは以下のようなコードとなります。やはり書き込み先がStreamであるため、それに関わる部分を除けば、シンプルなコードです。
//DataContractJsonSerializerをインスタンス化 var serializer = new DataContractJsonSerializer(typeof(FriendInfo)); //変換する.NETオブジェクトを作成 var friend = new FriendInfo() { Name = "Doi", Address = "Tokyo", Age = 32 }; //JSONデータを書き込むためのMemoryStreamを作成 var stream = new MemoryStream(); //(1)WriteObjectメソッドで.NETオブジェクトをJSONデータに変換 serializer.WriteObject(stream, friend); //(2)書き込んだMemoryStreamの内容を出力 stream.Position = 0; var reader = new StreamReader(stream); Console.Write(reader.ReadToEnd());
(1)では、DataContractJsonSerializerのWriteObjectメソッドを使い、.NETオブジェクトをJSONデータに変換しています。
(2)ではJSONデータの確認を行うため、MemoryStreamの内容を出力しています。WriteObjectメソッドの書き込み先がMemoryStreamのため、StreamをReader(.NETにおいて、連続する文字列を表すクラス)に変換するためのStreamReaderクラスを使うなど、多少ややこしいコードとなっています。出力結果は以下のようになります。
{"Address":"Tokyo","Age":32,"Name":"Doi"}
このように、DataContractJsonSerializerを使うことで、.NETオブジェクトとJSONデータの相互変換を行えます。事前に対応する.NETクラスの定義が必要なこと、読み書きはStreamを対象とすることに注意すれば、使用方法は簡単です。