「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
WCF や ASP.NET Web API で、指定の JSON を返す(送信する)方法を説明する。
JSON フォーマットとクラスの定義 †
JSONを返すサービスを作成する †
WCF で JSON を返す場合、既定では DataContractJsonSerializer? が使用される。
以下に注意する。
DataContractJsonSerializer? を使用 †
- WCF サービスを作成し、
- コントラクト部分に WebGet? 属性を追加する(POSTの場合は、WebInvoke?属性を追加を追加する。)
- UriTemplate? に、WebAPIに対応するURLパスの一部を設定する。
- ポイントは以下の 2 点。
- ResponseFormat? に、WebMessageFormat?.Json を指定し、JSON を返すことを宣言する。
- サービスメソッドの戻り値の型に、先ほど定義したクラス / プロパティの型を指定する。
- サービスを実装する。
[ServiceContract]
public interface IJSONService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetJson")]
Sample GetJson();
}
public class JSONService : IJSONService
{
public Sample GetJson()
{
// JSON にシリアライズする元となるオブジェクトを作成する
Sample sample = new Sample()
{
StringKey = "StringValue",
IntKey = 123,
ListKey = new List<string>() { "List1", "List2", "List3" }
};
// クライアントにデータを返す
return sample;
}
}
public class Sample
{
public string StringKey { get; set; }
public int IntKey { get; set; }
public List<string> ListKey { get; set; }
}
- "http://~/JSONService.svc/GetJson?" にリクエストを送ったときの実行結果
{"IntKey":123,"ListKey":["List1","List2","List3"],"StringKey":"StringValue"}
JSON.NETなどを使用 †
- WCF サービスを作成し、
- コントラクト部分に WebGet? 属性を追加する(POSTの場合は、WebInvoke?属性を追加を追加する。)
- UriTemplate? に、WebAPIに対応するURLパスの一部を設定する。
- サービスを実装する。
[ServiceContract]
public interface IJSONService2
{
[OperationContract]
[WebGet(UriTemplate = "GetJson")]
Message GetJson();
}
public class JSONService2 : IJSONService2
{
public Message GetJson()
{
// JSON にシリアライズする元となるオブジェクトを作成する
Sample2 sample = new Sample2()
{
key = new Dictionary<string, string>()
{
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"}
}
};
// JSON.NET を使用して JSON 形式にシリアライズ
string jsonStr = JsonConvert.SerializeObject(sample);
// 'X-Content-Type-Options: nosniff' ヘッダーを追加する
WebOperationContext.Current.OutgoingResponse.Headers.Add("X-Content-Type-Options", "nosniff");
// JSON を返す
return WebOperationContext.Current.CreateTextResponse(jsonStr,
"application/json; charset=utf-8",
Encoding.UTF8);
}
}
public class Sample2
{
public Dictionary<string, string> key { get; set; }
}
参考情報 †
WCF における JSON 処理の参考情報
注意点 †
- DataContractJsonSerializer?を使用する場合、相互運用性に注意する。
- WebサイトをIIS以下に配置した場合に例外が発生することがある。
にあるように、サービスのクラスに、
AspNetCompatibilityRequirements? 属性を追加する。
ASP.NET Web API は、既定で JSON.NET によって Serialize される。このため、Dictionary 型も問題なく Serialize できる。
設定 †
Web API の返すJSONフォーマット(JSONシリアライズのフォーマット)をWebApiConfigで、以下のように指定できる。
// JSON データにはCamelCaseを使用 (JSON.NET)
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
JSON.NETを使用 †
- Web アプリケーションに、Web API を作成する。
public class ValuesController : ApiController
{
// GET api/values
public Sample Get()
{
// JSON にシリアライズする元となるオブジェクトを作成する
Sample sample = new Sample()
{
key = new Dictionary<string, string>()
{
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"}
}
};
// JSON を返す
return sample;
}
}
public class Sample
{
public Dictionary<string, string> key { get; set; }
}
注意点 †
- ASP.NET Web API の注意点
既定では、ASP.NET Web API は、HTTP リクエストに含まれる Accept ヘッダーの内容により、クライアントに返すデータの形式が決められます。
- Acceptにapplication/xmlが含まれていた場合は、XML として返されます。(レスポンスのContent-Typeヘッダーがapplication/xmlとなる)
- Acceptにapplication/jsonが含まれていた場合は、JSON として返されます。(レスポンスのContent-Typeヘッダーがapplication/jsonとなる)
このため、常に JSON としてデータを受け取りたい場合は、リクエストヘッダーにAccept: application/jsonを必ずつけるようにしてください。
相互運用に関する注意事項 †
Java など、他プラットフォームとの相互運用を行なう際に注意すべき点。
DataContractJsonSerializer?の問題 †
既定の DataContractJsonSerializer では、Dictionary 型のオブジェクトを正しく扱えない。
DataContractJsonSerializer?の対策 †
その他のSerializerを使用する †
Dictionary 型のオブジェクトを扱う場合は、JSON.NET など、その他のSerializerを使用する。
JSON フォーマットを、コントラクトとする †
Java などの他プラットフォームとの相互運用を考えた場合、
いきなりPOJO または POCO をデータコントラクトとせず、
先ずは出力したい JSON フォーマットを確認する事から始める。
以下の手順で、
- 出力したい JSON フォーマットを決める
(これがデータコントラクトとなる)
- そのフォーマットにあわせて、
- Java であれば POJO
- .NET であれば POCO
クラスを作成する。
参考 †
Microsoft Azure が公開している REST API †
数個、Microsoft Azure が公開している REST API をピックアップした。
これらの REST API でも、JSON のフォーマットが明記されており、
JSON フォーマットレベルでデータコントラクトを結ぶ必要がある。
色々なSerializerと、その歴史 †
DataContractJsonSerializer?は、
WCFのデータコントラクトのSerializerとして使用されていたこともあり、
- 前述のように、相互運用性に難があり、
- また、匿名型などをシリアライズできない
などの問題があった。
データコントラクト不要な単方向のやり取りのために、JavaScriptSerializer?などのクラスも追加されたが、
これは、.NET3.5でサポートされなくなり、替わって、JSON.NETがデファクトになり、ASP.NET Web API の標準のシリアライザに採用された。
Tags: :.NET開発, :通信技術, :.NET Core, :ASP.NET, :ASP.NET Web API