2013-01-07 14 views
6

Mam problem z następującym JSON podczas deserializacji przy użyciu JSON.NET.Deserialize JSON nie działa z 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" 
       }] 
      } 
     }] 
    } 
} 

Używam następujących klas:

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

Kiedy próbuję deserializowania

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

mam następujący błąd:

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.

Przypuszczam problem występuje w notacji:

Czego mi brakuje, czy istnieje proste rozwiązanie tego problemu?

UPDATE:

więc ostatecznie problemem było to, że czasami tablicą JSON

"Skills": { 
       "Skill": [{ 

a czasem obiekt JSON

"Skills": { 
       "Skill": { 

Ale podczas wklejania/sprawdzając mój kod w walidatorach będzie zawsze sformatowany jako tablica JSON, więc sprawdziłem go za pomocą okna oglądania, aby zobaczyć surowy ciąg znaków json.

Stamtąd łatwo było oznaczyć nieruchomość z JsonConverter przypisują

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

i napisać konwerter:

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

nadzieję, że pomaga kogoś.

+0

Czytanie json z pliku, a deserializacji z kodem, wszystko działa dobrze dla mnie. – Pondidum

+3

Zaktualizowałem moje pytanie z odpowiedzią. –

+0

Fantastyczna odpowiedź. Powinieneś oznaczyć go jako zaakceptowaną odpowiedź. Idealne dla mnie. Jedyną zmianą, którą wprowadziłem, było stworzenie ogólnego konwertera zamiast twardego kodowania dla dowolnego typu (umiejętność w twoim przykładzie). –

Odpowiedz

4

Myślę, że z twoim aktualnym JSON, opisujesz, że Skill zawiera kolekcję, a nie Skills. Spróbuj tego JSON zamiast:

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

To samo odnosi się do sposobu definiowania kolekcji Persons.

EDIT:

Ten test przechodzi do mnie:

[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; } 
     } 
    } 
+0

Nie mogę zmienić JSON, gdybym mógł zrobić to tak, jak proponujesz. Ale to nadal jest prawidłowy JSON. –

+0

Głosowałem za twoją odpowiedzią, która popychała mnie we właściwym kierunku. Cała odpowiedź jest w mojej aktualizacji. –

Powiązane problemy