2013-01-07 40 views
6

Tôi gặp sự cố với JSON sau khi deserializing bằng JSON.NET.Deserialize JSON không hoạt động với 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" 
       }] 
      } 
     }] 
    } 
} 

Tôi đang sử dụng các loại sau đây:

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

Khi tôi cố gắng để deserialize

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

tôi đã nhận được lỗi sau:

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.

Tôi cho rằng vấn đề là trong ký hiệu:

"Skills": { 
      "Skill": [{ 

Tôi đang thiếu gì, có giải pháp dễ dàng cho vấn đề này không?

UPDATE:

Vì vậy, cuối cùng là vấn đề đã được rằng đó là đôi khi một mảng JSON

"Skills": { 
       "Skill": [{ 

và đôi khi một đối tượng JSON

"Skills": { 
       "Skill": { 

Nhưng khi dán/kiểm tra mã của tôi vào trình duyệt tính hợp lệ, nó sẽ luôn được định dạng dưới dạng một mảng JSON vì vậy tôi đã kiểm tra nó bằng cách sử dụng cửa sổ xem để xem chuỗi json thô.

Từ đó nó đã được dễ dàng để đánh dấu tài sản với một JsonConverter thuộc tính

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

và viết bộ chuyển đổi:

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

Hy vọng nó sẽ giúp ai đó.

+0

Reading json của bạn từ một tập tin, và deserializing với mã của bạn, tất cả hoạt động tốt đối với tôi. – Pondidum

+3

Tôi đã cập nhật câu hỏi của mình với câu trả lời. –

+0

Câu trả lời tuyệt vời. Bạn nên đánh dấu nó là câu trả lời được chấp nhận. Làm việc hoàn hảo cho tôi. Chỉ có thay đổi tôi thực hiện là làm cho bộ chuyển đổi chung chung thay vì mã hóa cứng cho bất kỳ loại nào (Kỹ năng trong ví dụ của bạn) –

Trả lời

4

Tôi nghĩ, với JSON hiện tại của bạn, bạn mô tả rằng Skill chứa một bộ sưu tập chứ không phải Skills. Hãy thử JSON này thay thế:

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

Điều tương tự cũng áp dụng cho cách bạn xác định bộ sưu tập Persons.

EDIT:

thử nghiệm này đi cho tôi:

[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

Tôi không thể thay đổi JSON, nếu tôi có thể tôi đã thực hiện nó như bạn đề xuất. Nhưng đây vẫn là JSON hợp lệ. –

+0

Tôi đã bỏ phiếu cho câu trả lời của bạn vì nó đã đẩy tôi đi đúng hướng. Toàn bộ câu trả lời là trong bản cập nhật của tôi. –

Các vấn đề liên quan