6

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

それが誰かに役立つことを願っています。

4

1 に答える 1

4

Skill現在のJSONでは、ではなくコレクションを含む記述をしていると思います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; }
        }
    }
于 2013-01-07T15:02:24.250 に答える