繁体   English   中英

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

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

我正在尝试将json结果反序列化为想要的对象。 我得到的结果是:

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

我希望此结果反序列化到我的对象:

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; }
}

我的反序列化看起来像这样:

 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);
 }

当我运行程序时,出现以下异常:

Newtonsoft.Json.JsonSerializationException:'无法反序列化当前JSON对象(例如{“ name”:“ value”})为类型'System.Collections.Generic.List`1 [ConsoleApp4.Rates]',因为该类型需要JSON数组(例如[1,2,3])正确反序列化。 要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化类型,使其成为普通的.NET类型(例如,不像整数这样的原始类型,也不像这样的集合类型)数组或列表),可以从JSON对象反序列化。 还可以将JsonObjectAttribute添加到类型中,以强制其从JSON对象反序列化。 路径“ rates.AUD”,第1行,位置49。”

如何将JSON反序列化为想要的对象?

更新1

还是我可以反序列化“费率”列表?

看一下您的JSON,特别是rates

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

很明显,这是一个JSON对象,因为它具有键值对。 但是,查看您的代码,您已将相应的属性( Rates )定义为IList

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

我们了解您定义Rates类背后的原因。 您认为通过定义该类,NewtonSoft将以您希望的方式反序列化rates 但是,这是不可能的,因为rates不是数组,因此将其反序列化为任何种类的IList是不可能的。

最简单,最明确的解决方案是使用字典:

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

但是,如果您不想使用字典,则需要像这样修改JSON,您的解决方案将起作用:

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

通过将rates转换为数组,并使其内容对象而不是键值对,NewtonSoft可以将rates反序列化为列表,并将其内容反序列化为Rates类的实例。

我同意其他人的意见:您应该使用字典。 为了实现到最终对象结构的转换,您可以使用例如带有显式强制转换运算符的中间类。

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