反序列化Json C#错误

时间:2017-03-21 04:09:24

标签: c# .net 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; }
    }

这是我的方法,我得到并反序列化我的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的方式:&#34; http://api.promasters.net.br/cotacao/v1/valores&#34;回报。

{
  "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(&#34; http://api.promasters.net.br/cotacao/v1/valores&#34;);

它是以字符串形式接收Json,但没有收到任何东西,它就像一个空字符串。

3 个答案:

答案 0 :(得分: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/上似乎可以使用{<3}}:

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

有关是否处置HttpClient

的讨论,另请参阅this post

答案 1 :(得分:0)

这里的问题是反序列化的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;
} 

答案 2 :(得分:0)

问题是返回的json包含字典中的Valores集合,您正试图将响应映射到单个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...
    }
}