【问题标题】:Deserialize JSON not working with JSON.NET反序列化 JSON 不适用于 JSON.NET
【发布时间】:2013-01-07 14:43:07
【问题描述】:

我在使用 JSON.NET 反序列化时遇到以下 JSON 问题。

{
    "?xml": {
        "@version": "1.0",
        "@encoding": "utf-8"
    },
    "Persons": {
        "Person": [{
            "@Id": "1",
            "@Name": "John",
            "@Surname": "Smith"         
        },
        {
            "@Id": "2",
            "@Name": "John",
            "@Surname": "Smith",
            "Skills": {
                "Skill": [{
                    "@Id": "1",
                    "@Name": "Developer"                    
                },
                {
                    "@Id": "2",
                    "@Name": "Tester"
                }]
            }
        }]
    }
}

我正在使用以下课程:

public class RootObject
{
    public Xml xml { get; set; }
    public Persons Persons { get; set; }
}

public class Xml
{
    public string version { get; set; }
    public string encoding { get; set; }
}

public class Persons
{
    public List<Person> Person { get; set; }
}
public class Skill
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Skills
{
    public List<Skill> Skill { get; set; }
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public Skills Skills { get; set; }
}

当我尝试反序列化时

RootObject persons = JsonConvert.DeserializeObject<RootObject>(json);

我收到以下错误:

无法反序列化当前 JSON 对象(例如 {"name":"value"}) 输入类型 'System.Collections.Generic.List`1[Project.Models.Persons.Skill]' 因为该类型需要一个 JSON 数组(例如 [1,2,3])来反序列化 正确。要修复此错误,请将 JSON 更改为 JSON 数组 (例如 [1,2,3])或更改反序列化类型,使其成为正常的 .NET 类型(例如,不是像整数这样的原始类型,也不是集合 可以从 JSON 反序列化的数组或列表等类型 目的。 JsonObjectAttribute 也可以添加到类型中来强制它 从 JSON 对象反序列化。

我想问题出在符号上:

"Skills": {
            "Skill": [{

我错过了什么,这个问题有简单的解决方案吗?

更新:

所以最后的问题是它有时是一个 JSON 数组

"Skills": {
                "Skill": [{

有时是 JSON 对象

"Skills": {
                "Skill": {

但是当将我的代码粘贴/检查到验证器中时,它总是会被格式化为 JSON 数组,所以我使用监视窗口对其进行了检查以查看原始 json 字符串。

从那里很容易用 JsonConverter 属性标记属性

public class Skills
    {
        [JsonConverter(typeof(MyConverter))]
        public List<Skill> Skill { get; set; }
    }

并编写转换器:

public class MyConverter : JsonConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.StartArray)
            {
                return serializer.Deserialize<List<Skill>>(reader);
            }
            else
            {
                Skill skill = serializer.Deserialize<Skill>(reader);
                return new List<Skill>(new[] { skill});
            }
        }      

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteValue(value);
        }
    }

希望它对某人有所帮助。

【问题讨论】:

  • 从文件中读取你的 json,并用你的代码反序列化,这对我来说一切正常。
  • 我已经用答案更新了我的问题。
  • 很棒的答案。您应该将其标记为已接受的答案。对我来说非常完美。我所做的唯一更改是使转换器通用,而不是为任何一种类型硬编码(您的示例中的技能)
  • @GregLoehr 很高兴它有帮助。我也实现了一个通用转换器。这只是给定问题的一个示例。
  • 如果您回答自己的问题,答案应该是下面的实际答案

标签: c# json json.net deserialization


【解决方案1】:

我认为,使用您当前的 JSON,您正在描述 Skill 包含一个集合,而不是 Skills。试试这个 JSON:

        "Skills": [
            {
                "@Id": "1",
                "@Name": "Developer"
            },
            {
                "@Id": "2",
                "@Name": "Tester"
            }
        ]

同样的事情也适用于您定义Persons 集合的方式。

编辑:

我通过了这个测试:

    [TestFixture]
    public class JSONTester
    {
        [Test]
        public void Json_deserialize()
        {
            var json = @"{
    ""?xml"": {
        ""@version"": ""1.0"",
        ""@encoding"": ""utf-8""
    },
    ""Persons"": {
        ""Person"": [{
            ""@Id"": ""1"",
            ""@Name"": ""John"",
            ""@Surname"": ""Smith""         
        },
        {
            ""@Id"": ""2"",
            ""@Name"": ""John"",
            ""@Surname"": ""Smith"",
            ""Skills"": {
                ""Skill"": [{
                    ""@Id"": ""1"",
                    ""@Name"": ""Developer""                    
                },
                {
                    ""@Id"": ""2"",
                    ""@Name"": ""Tester""
                }]
            }
        }]
    }
}";

            var persons = JsonConvert.DeserializeObject<RootObject>(json);

            Assert.AreEqual(persons.Persons.Person[1].Skills.Skill.Count, 2);

        }

        public class RootObject
        {
            public Xml xml { get; set; }
            public Persons Persons { get; set; }
        }

        public class Xml
        {
            public string version { get; set; }
            public string encoding { get; set; }
        }

        public class Persons
        {
            public List<Person> Person { get; set; }
        }
        public class Skill
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

        public class Skills
        {
            public List<Skill> Skill { get; set; }
        }

        public class Person
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Surname { get; set; }
            public Skills Skills { get; set; }
        }
    }

【讨论】:

  • 我无法更改 JSON,如果可以的话,我会按照您的建议进行操作。但这仍然是一个有效的 JSON。
  • 我对你的回答投了赞成票,因为它把我推向了正确的方向。整个答案在我的更新中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
相关资源
最近更新 更多