Northwind ODataサービスを使用しようとしています。
http://services.odata.org/V3/OData/OData.svc/Products?$format=json
それを製品のコレクションにデシリアライズします:
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(new Uri(url));
ObservableCollection<Product> products = await response.Content.ReadAsAsync<ObservableCollection<Product>>();
}
しかし、シリアライザーはodata.metadata
部分とそこに2つのodata.type
レコードがあるという事実を好まないようです(それらが何であるかはわかりません)。
これを行う簡単な方法はありますか?
Json.Net を使用する
using (var client = new HttpClient())
{
var json = await client.GetStringAsync("http://services.odata.org/V3/OData/OData.svc/Products?$format=json");
var odata = JsonConvert.DeserializeObject<OData>(json);
}
public class Value
{
[JsonProperty("odata.type")]
public string Type { set; get; }
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime ReleaseDate { get; set; }
public DateTime? DiscontinuedDate { get; set; }
public int Rating { get; set; }
public double Price { get; set; }
}
public class OData
{
[JsonProperty("odata.metadata")]
public string Metadata { get; set; }
public List<Value> Value { get; set; }
}
Odataからの応答のクラスを定義します(これは一般的な定義なので、どのタイプでも使用できます)。
internal class ODataResponse<T>
{
public List<T> Value { get; set; }
}
次のようにデシリアライズします。
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(new Uri(url));
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ODataResponse<Product>>(json);
var products = result.Value;
}
Visual Studioを使用している場合、素晴らしいCLRクラス生成機能が組み込まれています。
その後、Json.NETを使用して、これらのクラスにデシリアライズします(L.Bの回答を参照)。
ODataサービスを直接使用するための.NETクライアントがあります。 V3 odataサービスの場合、 Simple.OData.Client 、 OData v1-3のODataLib で試すことができます。 V3 ODataサービスの場合、 OData Client Code Generator で試すことができます。 ODataクライアントのその他のライブラリについては、 http://www.odata.org/libraries/ を参照できます。
odata.metadata
部分に起因する逆シリアル化の問題を管理する別の潜在的な方法は、odata応答にメタデータが含まれていないことを要求することです。これは、httpクライアントのデフォルトのリクエストヘッダーを使用して実行できます。
client.DefaultRequestHeaders.Add("Accept", "application/json;odata.metadata=none");
これにより、オブジェクトをReadAsAsyncで逆シリアル化できます。
var products = response.Content.ReadAsAsync<Dictionary<string, ObservableCollection<Product>>>().Result["value"]
これは、応答を処理するために別のクラスを作成するよりもずっときれいに思えます。 .Result
を使用することは、コードが非同期ではないため最良の方法ではないかもしれませんが、私のアプリケーションでは重要ではなく、コードの行数を少なくしました。