C# 如何反序列化ODataJSON?

C# 如何反序列化ODataJSON?,c#,json,odata,C#,Json,Odata,我正在尝试使用Northwind OData服务: 并将其反序列化为一组产品: using (var client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync(new Uri(url)); ObservableCollection<Product> products = await response.Content.ReadAsA

我正在尝试使用Northwind OData服务:

并将其反序列化为一组产品:

    using (var client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(new Uri(url));
        ObservableCollection<Product> products = await response.Content.ReadAsAsync<ObservableCollection<Product>>();
    }
使用(var-client=new-HttpClient())
{
HttpResponseMessage response=wait client.GetAsync(新Uri(url));
ObservableCollection products=await response.Content.ReadAsAsync();
}
但是序列化程序似乎不喜欢
odata.metadata
部分,也不喜欢有2条
odata.type
记录(不确定它们是什么)

有没有一个简单的方法可以做到这一点

使用

使用(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);
}

公共类值
{
[JsonProperty(“odata.type”)]
公共字符串类型{set;get;}
公共int ID{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
公共日期时间释放日期{get;set;}
公共日期时间?终止日期{get;set;}
公共整数评级{get;set;}
公共双价{get;set;}
}
公共级小田
{
[JsonProperty(“odata.metadata”)]
公共字符串元数据{get;set;}
公共列表值{get;set;}
}

有.NET客户端可直接使用OData服务。对于V3 odata服务,您可以尝试使用。对于V3 OData服务,您可以尝试使用。OData客户端的其他库,您可以参考。

如果您使用的是Visual Studio,则内置了一个出色的CLR类生成功能

  • 将OData有效负载复制到剪贴板中
  • 在Visual Studio中,选择菜单选项“编辑”-->“粘贴特殊”-->将JSON粘贴为对象类

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

    为来自odata的响应定义一个类(这是一个通用定义,因此您可以将其用于任何类型):

    内部类ODataResponse
    {
    公共列表值{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;
     }
    
    使用(var-client=new-HttpClient())
    {
    HttpResponseMessage response=wait client.GetAsync(新Uri(url));
    var json=await response.Content.ReadAsStringAsync();
    var result=JsonConvert.DeserializeObject(json);
    var产品=结果值;
    }
    
    管理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"]
    
    var products=response.Content.ReadAsAsync().Result[“value”]
    

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

    顺便问一下,所有oData服务都会以这种形式返回数据吗?因此,我可以假设北风的客户将是相似的,或者我必须手工制作每项服务吗?@Graeme不知道oData服务。我只是根据您的url准备了这个示例。您也可以将其设计为动态。@Brandsdal如何解决它
    odata.type
    问题
    type
    不是
    odata
    对象的属性。这是属性的名称。@Graeme您不能依赖oData服务返回此形状的数据。如果您只看到“粘贴XML类”菜单选项,请使用“粘贴为XML”菜单粘贴JSON。IDE看到这一点,然后添加“粘贴JSON为类”菜单项。它将粘贴到光标所在的位置,因此一个新的空白虚拟类文件可以作为粘贴目标。VS处理一些奇怪的元素要比站点好得多。为什么System.Text.Json(使用
    JsonSerializer.Deserialize()
    )不起作用?
    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;
     }
    
    client.DefaultRequestHeaders.Add("Accept", "application/json;odata.metadata=none");
    
    var products = response.Content.ReadAsAsync<Dictionary<string, ObservableCollection<Product>>>().Result["value"]