【问题标题】:Deserialize Json C# error反序列化 Json C# 错误
【发布时间】:2017-03-21 22:14:36
【问题描述】:

嗯,我是编程新手,但遇到了一个问题。

这是我的班级Valores

public class Valores
    {
        [JsonProperty("nome")]
        public string Nome { get; set; }
        [JsonProperty("valor")]
        public double Valor { get; set; }
        [JsonProperty("ultima_consulta")]
        public int UltimaConsulta { get; set; }
        [JsonProperty("fonte")]
        public string Fonte { get; set; }
    }

这是我获取和反序列化 Json 的方法

public static async Task<Valores> GetAsync()
    {
        Valores valores = null;

            using (var client = new HttpClient())
            {
                var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
                valores = JsonConvert.DeserializeObject<Valores>(json);
            }

        return valores;
    }

这是 json 的方式:“http://api.promasters.net.br/cotacao/v1/valores”返回。

{
  "status": true,
  "valores": {
    "USD": {
      "nome": "Dólar",
      "valor": 3.0717,
      "ultima_consulta": 1490040302,
      "fonte": "UOL Economia - http://economia.uol.com.br/"
    },
    "EUR": {
      "nome": "Euro",
      "valor": 3.3002,
      "ultima_consulta": 1490040302,
      "fonte": "UOL Economia - http://economia.uol.com.br/"
    },
    "ARS": {
      "nome": "Peso Argentino",
      "valor": 0.1965,
      "ultima_consulta": 1490040302,
      "fonte": "UOL Economia - http://economia.uol.com.br/"
    },
    "GBP": {
      "nome": "Libra Esterlina",
      "valor": 3.7966,
      "ultima_consulta": 1490040302,
      "fonte": "UOL Economia - http://economia.uol.com.br/"
    },
    "BTC": {
      "nome": "Bitcoin",
      "valor": 3472,
      "ultima_consulta": 1490067603,
      "fonte": "Mercado Bitcoin - http://www.mercadobitcoin.com.br/"
    }
  }
}

我不知道我做错了什么,因为这个

var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");

本来是接收字符串中的Json,但没有接收到任何东西,就像一个空字符串。

【问题讨论】:

    标签: c# .net json


    【解决方案1】:

    我做了一些实验,似乎网站需要将user agent 请求字符串设置为某个值才能返回 JSON。而且,我的意思是,字符串"something" 似乎有效,字符串"Wget/1.11.4" 也有效。您应该检查documentation(葡萄牙语)以确保对本网站的程序访问没有任何限制,并遵守这些访问限制(如果有)。

    另外,您的数据模型不反映您的 JSON。您需要一个更高级别的根对象,如下所示:

    public class RootObject
    {
        public RootObject() { this.valores = new Dictionary<string, Valores>(); }
    
        public bool status { get; set; }
        public Dictionary<string, Valores> valores { get; set; }
    }
    

    这是一个sample fiddle,它通过设置用户代理成功地从站点下载和反序列化 JSON。它使用WebClient,因为这似乎在https://dotnetfiddle.net/ 上可用:

    public static async Task<RootObject> GetAsync()
    {
        using (var client = new WebClient())
        {
            client.Headers["User-Agent"] = "something";
            var json = await client.DownloadStringTaskAsync(@"http://api.promasters.net.br/cotacao/v1/valores");
            var root = JsonConvert.DeserializeObject<RootObject>(json);
            return root;
        }   
    }
    

    对于HttpClient,我认为应该是(未经测试):

    public static async Task<RootObject> GetAsync()
    {
        var client = new HttpClient();
    
        client.DefaultRequestHeaders.Add("User-Agent", "something");
        var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
        return JsonConvert.DeserializeObject<RootObject>(json);
    }
    

    另请参阅this post,了解是否处置HttpClient

    【讨论】:

      【解决方案2】:

      这里的问题是反序列化的 json 没有正确映射到对象。尝试在您的模型(Valores)上创建一个包装类,然后尝试映射。

      public class Valores
      {
          [JsonProperty("nome")]
          public string Nome { get; set; }
          [JsonProperty("valor")]
          public double Valor { get; set; }
          [JsonProperty("ultima_consulta")]
          public int UltimaConsulta { get; set; }
          [JsonProperty("fonte")]
          public string Fonte { get; set; }
      }
      
      public class ValoresList
      {
          public boolean status { get; set; }
          public Valores USD { get; set; }
          public Valores EUR { get; set; }
          public Valores ARS { get; set; }
          public Valores GBP { get; set; }
          public Valores BTC { get; set; }
      }
      

      然后将包装类映射到反序列化的 json。

      public static async Task<ValoresList> GetAsync()
      {
          ValoresList valores = null;
      
          using (var client = new HttpClient())
          {
              var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
              valores = JsonConvert.DeserializeObject<ValoresList>(json);
          }
      
          return valores;
      } 
      

      【讨论】:

        【解决方案3】:

        问题是返回的 json 包含字典中的 Valore 集合,您正在尝试将响应映射到单个 Valore 对象。

        您的容器希望看起来像这样。字典的键是货币的字符串表示形式。

        class Container
        {
            public bool Status { get; set; }
            public Dictionary<string, ValorInfo> Valores { get; set; }
        }
        

        你的 Valor 类是好的,我将它重命名以防止类名与 Valor 属性发生冲突。

        class ValorInfo
        {
            [JsonProperty("nome")]
            public string Nome { get; set; }
            [JsonProperty("valor")]
            public double Valor { get; set; }
            [JsonProperty("ultima_consulta")]
            public int UltimaConsulta { get; set; }
            [JsonProperty("fonte")]
            public string Fonte { get; set; }
        }
        

        最后这就是你使用它的方式,@dbc 用于发现用户代理要求的道具,这让我很难过!

        async void Main()
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
                client.DefaultRequestHeaders.Add("User-Agent", "linqpad");
        
                var response = await client.GetAsync("http://api.promasters.net.br/cotacao/v1/valores");
                response.EnsureSuccessStatusCode();
        
                var container = await response.Content.ReadAsAsync<Container>();
        
                // do stuff with container...
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多