如何反序列化oData JSON?

我正在尝试使用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 products = await response.Content.ReadAsAsync<ObservableCollection>(); } 

但是序列化程序似乎不喜欢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(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 { get; set; } } 

为odata的响应定义一个类(它是一个通用的定义,所以你可以在任何类型使用它):

 internal class ODataResponse { public List 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>(json); var products = result.Value; } 

如果您使用的是Visual Studio,则内置了一个出色的CLR Class Generationfunction。

  1. 将OData有效负载复制到剪贴板
  2. 在Visual Studio中,选择菜单选项编辑 – > 选择性粘贴 – >将JSON粘贴为对象类

然后,您可以使用Json.NET反序列化到这些类中(如LB的答案中所述)。

有一个.NET客户端可以直接使用OData服务。 对于V3 odata服务,您可以尝试使用Simple.OData.Client , ODataLib for OData v1-3 。 对于V3 OData服务,您可以尝试使用OData客户端代码生成器 。 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>>().Result["value"] 

这似乎比编写另一个类来处理响应更清晰。 使用.Result可能不是最好的方法,因为代码不是异步的,但它在我的应用程序中并不重要,并使代码占用更少的行。