2013-01-07 8 views
6

Ich habe ein Problem mit dem folgenden JSON beim Deserialisieren mit JSON.NET.Deserialize JSON funktioniert nicht mit 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" 
       }] 
      } 
     }] 
    } 
} 

Ich verwende die folgenden Klassen:

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

Wenn ich

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

zu deserialisieren versuchen bekam ich folgende Fehlermeldung:

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.

ich nehme an Problem ist in der Notation:

"Skills": { 
      "Skill": [{ 

Was fehlt mir, gibt es eine einfache Lösung für dieses Problem?

UPDATE:

So endlich das Problem war, dass es manchmal ein JSON-Array

"Skills": { 
       "Skill": [{ 

und manchmal ein JSON-Objekt

"Skills": { 
       "Skill": { 

Aber wenn mein Code einfügen/Prüfung In Validatoren würde es immer als JSON-Array formatiert werden, also habe ich es mit Hilfe des Beobachtungsfensters untersucht, um die rohe JSON-Zeichenkette zu sehen.

Von dort war es einfach, die Immobilie mit einem JsonConverter

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

Attribut zu markieren und den Konverter schreiben:

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

Hoffe, dass es jemand hilft.

+0

aus einer Datei Ihre json Lesen, und Deserialisieren mit Ihrem Code, es funktioniert gut für mich. – Pondidum

+3

Ich habe meine Frage mit einer Antwort aktualisiert. –

+0

Fantastische Antwort. Sie sollten es als die akzeptierte Antwort markieren. Arbeitete perfekt für mich. Die einzige Änderung, die ich gemacht habe, war, den Konverter generisch zu machen anstatt ihn für irgendeinen Typ zu kodieren (Fähigkeit in deinem Beispiel) –

Antwort

4

Ich denke, mit Ihrem aktuellen JSON beschreiben Sie, dass Skill eine Sammlung enthält, nicht Skills. Versuchen Sie, diese JSON statt:

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

Das gleiche gilt für, wie Sie die Persons Sammlung definieren.

EDIT:

Dieser Test geht für mich:

[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

Ich kann das JSON nicht ändern, wenn ich könnte ich hätte es getan, wie Sie vorschlagen. Aber das ist immer noch ein gültiger JSON. –

+0

Ich habe deine Antwort gewählt, da sie mich in die richtige Richtung gebracht hat. Die ganze Antwort ist in meinem Update. –

Verwandte Themen