简体   繁体   English

如何在C#中将JSON反序列化为复杂对象

[英]How to deserialize JSON to complex object in C#

I'm trying to deserialize json result to wanted object. 我正在尝试将json结果反序列化为想要的对象。 The result I'm getting is: 我得到的结果是:

{
    "base": "EUR",
    "date": "2017-06-30",
    "rates": {
        "AUD": 1.4851,
        "BGN": 1.9558,
        "BRL": 3.76,
        "CAD": 1.4785
    }
}

I want this result to deserialize to my object: 我希望此结果反序列化到我的对象:

public class ExchangeRates
{
    public string Base { get; set; }

    public DateTime Date { get; set; }

    public IList<Rates> Rates { get; set; }
}

public class Rates
{
    public string Name { get; set; }

    public decimal Value { get; set; }
}

my deserialization looks like this: 我的反序列化看起来像这样:

 using (var httpClient = new HttpClient())
 {
     var response = httpClient.GetAsync("http://api.fixer.io/latest").Result;
     var result = response.Content.ReadAsStringAsync().Result;
     var values = JsonConvert.DeserializeObject<ExchangeRates>(result);
 }

When I run the program I get following exception: 当我运行程序时,出现以下异常:

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'System.Collections.Generic.List`1[ConsoleApp4.Rates]' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly. Newtonsoft.Json.JsonSerializationException:'无法反序列化当前JSON对象(例如{“ name”:“ value”})为类型'System.Collections.Generic.List`1 [ConsoleApp4.Rates]',因为该类型需要JSON数组(例如[1,2,3])正确反序列化。 To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. 要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化类型,使其成为普通的.NET类型(例如,不像整数这样的原始类型,也不像这样的集合类型)数组或列表),可以从JSON对象反序列化。 JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. 还可以将JsonObjectAttribute添加到类型中,以强制其从JSON对象反序列化。 Path 'rates.AUD', line 1, position 49.' 路径“ rates.AUD”,第1行,位置49。”

How can I deserialize JSON to my wanted object?? 如何将JSON反序列化为想要的对象?

UPDATE 1 更新1

Or maybe I can just deserialize 'rates' list? 还是我可以反序列化“费率”列表?

Take a look at your JSON, specifically rates : 看一下您的JSON,特别是rates

"rates": {
    "AUD": 1.4851,
    "BGN": 1.9558,
    "BRL": 3.76,
    "CAD": 1.4785
}

This is very clearly a JSON object, as it has key-value pairs. 很明显,这是一个JSON对象,因为它具有键值对。 However, looking at your code, you have defined the corresponding property ( Rates ) as an IList : 但是,查看您的代码,您已将相应的属性( Rates )定义为IList

public IList<Rates> Rates { get; set; }

I understand your reasoning behind defining the Rates class. 我们了解您定义Rates类背后的原因。 You think that by defining that class, NewtonSoft will deserialize rates the way you want it to. 您认为通过定义该类,NewtonSoft将以您希望的方式反序列化rates However, this is impossible because rates is not an array, and therefore deserializing it into any kind of IList is impossible. 但是,这是不可能的,因为rates不是数组,因此将其反序列化为任何种类的IList是不可能的。

The easiest and most clear cut solution is to use a dictionary: 最简单,最明确的解决方案是使用字典:

public Dictionary<string, decimal> Rates { get; set; }

However, if you don't want to use a dictionary, you need to modify your JSON like so and your solution will work: 但是,如果您不想使用字典,则需要像这样修改JSON,您的解决方案将起作用:

"rates":[  
  {  
     "Name":"AUD",
     "Value":1.4851
  },
  {  
     "Name":"BGN",
     "Value":1.9558
  },
  {  
     "Name":"BRL",
     "Value":3.76
  },
  {  
     "Name":"CAD",
     "Value":1.4785
  }
]

By converting rates to an array, and making its contents objects instead of key-value pairs, NewtonSoft can deserialize rates as a list, and its contents as instances of the Rates class. 通过将rates转换为数组,并使其内容对象而不是键值对,NewtonSoft可以将rates反序列化为列表,并将其内容反序列化为Rates类的实例。

I agree with the other guys comments: you should use a Dictionary. 我同意其他人的意见:您应该使用字典。 To achieve the conversion to your final object structure you can use for example an intermediary class with an explicit cast operator. 为了实现到最终对象结构的转换,您可以使用例如带有显式强制转换运算符的中间类。

using System;
using Newtonsoft.Json;
using System.Collections.Generic;

public class Program
{
    public void Main()
    {
        var result = @"{
        ""base"": ""EUR"",
        ""date"": ""2017-06-30"",
        ""rates"": {
            ""AUD"": 1.4851,
            ""BGN"": 1.9558,
            ""BRL"": 3.76,
            ""CAD"": 1.4785
        }}";

        var values = (ExchangeRates) JsonConvert.DeserializeObject<TempExchangeRates>(result);


        Console.WriteLine(values.Base);
        Console.WriteLine(values.Date);

        foreach(var rate in values.Rates)
            Console.WriteLine(rate.Name + ": " + rate.
    }
}

public class TempExchangeRates
{
    public string Base { get; set; }
    public DateTime Date { get; set; }
    public Dictionary<string,decimal> Rates { get; set; }
    public static explicit operator ExchangeRates(TempExchangeRates tmpRates)
    {
        var xRate = new ExchangeRates();

        xRate.Base = tmpRates.Base;
        xRate.Date = tmpRates.Date;
        xRate.Rates = new List<Rates>();

        foreach(var de in tmpRates.Rates)
            xRate.Rates.Add(new Rates{Name = de.Key, Value = de.Value});

        return xRate;
    }
}


public class ExchangeRates
{
    public string Base { get; set; }
    public DateTime Date { get; set; }
    public IList<Rates> Rates { get; set; }
}

public class Rates
{
    public string Name { get; set; }
    public decimal Value { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM