I have a problem with the following JSON when deserializing using JSON.NET.
{
"?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"
}]
}
}]
}
}
I'm using the following classes:
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; }
}
When i try to deserialize
RootObject persons = JsonConvert.DeserializeObject<RootObject>(json);
i got the following error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Project.Models.Persons.Skill]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
I suppose the problem is in the notation:
"Skills": {
"Skill": [{
What am I missing, is there an easy solution to this problem?
UPDATE:
So finally the problem was that it was sometimes a JSON array
"Skills": {
"Skill": [{
and sometimes a JSON object
"Skills": {
"Skill": {
But when pasting/checking my code into validators it would always be formatted as a JSON array so i've inspected it using watch window to see the raw json string.
From there it was easy to mark the property with a JsonConverter attribute
public class Skills
{
[JsonConverter(typeof(MyConverter))]
public List<Skill> Skill { get; set; }
}
and write the converter:
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);
}
}
Hope it helps somebody.
I think, with your current JSON, you are describing that Skill
contains a collection, not Skills
. Try this JSON instead:
"Skills": [
{
"@Id": "1",
"@Name": "Developer"
},
{
"@Id": "2",
"@Name": "Tester"
}
]
The same thing applies to how you are defining the Persons
collection.
EDIT:
This test passes for me:
[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; }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With