【问题标题】:json newtonsoft : Deserialize Object containing a list of stringjson newtonsoft:反序列化包含字符串列表的对象
【发布时间】:2014-03-22 16:15:40
【问题描述】:

我对这个 json 有以下问题:

{
"EVTS": {
"EVT": [
  { "ID": "123456",
    "KEY1" : "somekey",
    "CATEG": [
      "cat1",
      "cat2",
      "cat3"
    ]
  }
  ]}
  }

还有这个 c# 类:

public class myClass{
    public string ID { get; set; }
    public string KEY1 { get; set; } 

    public list<string> CATEG { get; set; } 
}

public class ESObject1
{

    [JsonProperty("EVT")]
    public List<myClass> EVT { get; set; }
}

public class ESObject0
{

    [JsonProperty("EVTS")]
    public ESObject1 EVTS { get; set; }
}

}

这里我称之为反序列化器:

ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);

但是最后这段代码不起作用,我抛出了这个异常:System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List1[System.String]。`

我使用string [] 而不是list&lt;string&gt; 并且只有string 似乎没有任何效果。

请问我怎样才能正确反序列化这个对象。

谢谢。

【问题讨论】:

  • 对我有用,假设在“somekey”之后缺少逗号只是一个错字,这个 json 应该可以反序列化。请发布真正产生相同错误的 Json 示例。

标签: c# asp.net .net json.net json-deserialization


【解决方案1】:

正如此工作示例所示,您的代码似乎没有任何明显的问题:

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

public class myClass
{
    public string ID { get; set; }
    public string KEY1 { get; set; } 
    public List<string> CATEG { get; set; } 
}

public class ESObject1
{
    [JsonProperty("EVT")]
    public List<myClass> EVT { get; set; }
}

public class ESObject0
{
    [JsonProperty("EVTS")]
    public ESObject1 EVTS { get; set; }
}


class Program
{
    static void Main()
    {
        string json = 
        @"{
            ""EVTS"": {
                ""EVT"": [
                    {
                        ""ID"": ""123456"",
                        ""KEY1"": ""somekey"",
                        ""CATEG"": [
                            ""cat1"",
                            ""cat2"",
                            ""cat3""
                        ]
                    }
                ]
            }
        }";

        ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
        foreach (string item in globalobject.EVTS.EVT[0].CATEG)
        {
            Console.WriteLine(item);
        }
    }
}

也许您只是向反序列化器提供了错误的 json 值,它看起来不像您的问题中显示的那样。顺便说一句,您的问题中显示的 JSON 无效,因为您在 KEY1 属性声明之后缺少 ,


更新:

现在您已经展示了您的真实 JSON(来自 http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&f=JSON),似乎有一行 CATEG 不是字符串数组而是简单字符串:

""CATEG"": ""Conférence""

现在这是一个非常糟糕的设计,因为它们混合了数组和简单的属性。恐怕为了处理这种情况,您需要使用JObjects 并通过测试实际的底层类型来提取您需要的信息。

例如:

var obj = JObject.Parse(json);
var events = (JArray)obj["EVTS"]["EVT"];
foreach (JObject evt in events)
{
    var categories = evt["CATEG"];
    if (categories is JArray)
    {
        // you've got a list of strings so you can loop through them
        string[] cats = ((JArray)categories)
            .Select(x => x.Value<string>())
            .ToArray();
    }
    else
    {
        // you've got a simple string
        string cat = categories.Value<string>();
    }
}

【讨论】:

  • 我已经简化了 json 来发布问题。
  • 好吧,你已经简化了它,我用它展示了一个工作示例。如果您的实际 JSON 不同,恐怕我无法读懂您的想法并知道它的样子,甚至在不知道问题所在的情况下也无法提供帮助。
  • 实际上我从像这样HttpResponseMessage response = await client.GetAsync("http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&amp;f=JSON"); 这样的外部url 获取json 然后我把它放到一个字符串string json = await response.Content.ReadAsStringAsync(); 当我在我的课堂上评论CATEG 时它起作用了!!!
  • 对不起!但你是对的,我知道我的问题在哪里。一些 CATEG r 不是数组,它们是简单的字符串 :( 我不知道该怎么做,但我不知道你的答案。
  • 我已经更新了我的答案,以说明如何使用弱类型 JObject 来实现这一目标。
【解决方案2】:

我已经做过很多次了,很多次头疼。我的建议是获取 json 输出并使用与此类似的工具为您编写课程 (http://json2csharp.com/)。

然后检查所有可以为空的变量并在需要的地方添加可以为空的类型(例如,使用 int? for int)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多