我正在尝试使用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
个记录的事实(不确定它们是什么)。
有一种简单的方法吗?
答案 0 :(得分:33)
使用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; }
}
答案 1 :(得分:13)
为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;
}
答案 2 :(得分:7)
如果您使用的是Visual Studio,则内置了一个非常棒的CLR Class Generation功能。
然后,您可以使用Json.NET反序列化到这些类中(如L.B&#39的回答中所述)。
答案 3 :(得分:3)
有.NET客户端直接使用OData服务。对于V3 odata服务,您可以尝试使用Simple.OData.Client,ODataLib for OData v1-3。对于V3 OData服务,您可以尝试使用OData Client Code Generator。 OData客户端的其他库,您可以参考http://www.odata.org/libraries/。
答案 4 :(得分:0)
管理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
可能不是最好的方法,因为代码不是异步的,但它在我的应用程序中并不重要,并使代码占用更少的行。