2012-06-11 45 views
6

Tôi đang làm việc với API bên ngoài trả về thuộc tính dưới dạng mảng hoặc dưới dạng đối tượng, tùy thuộc vào số lượng. Một cách tốt để xử lý điều này là gì?Phân tích cú pháp đối tượng JSON không mảng thành mảng với Json.net

Trở như mảng:

{ 
    "contacts": { 
     "address": [ 
      { 
       "id": "47602070", 
       "type": "Work", 
       "street": "MyStreet", 
       "city": "MyCity", 
       "zip": "12345", 
       "country": "USA" 
      }, 
      { 
       "id": "47732816", 
       "type": "GPS", 
       "street": "50.0,30.0" 
      } 
     ] 
    } 
} 

Trở như đối tượng:

{ 
    "contacts": { 
     "address": { 
      "id": "47602070", 
      "type": "Work", 
      "street": "MyStreet", 
      "city": "MyCity", 
      "zip": "12345", 
      "country": "USA" 
     } 
    } 
} 

Tôi đang nghĩ đến một cách giải quyết sẽ được sử dụng một deserializer tùy chỉnh và trả về một mảng có độ dài 1 cho trường hợp đối tượng và mặc định deserialization cho trường hợp mảng, nhưng tôi không biết làm thế nào để làm điều đó được nêu ra.

Tôi đã cố gắng deserializing đối tượng vào một mảng và hy vọng Json.net sẽ xử lý trường hợp này cho tôi, nhưng không có súc sắc.

Trả lời

3

Trình chuyển đổi JSON.NET tùy chỉnh có thể thực hiện thủ thuật tại đây. Nó không phải là khó.

Đối với thuộc tính DateTime, bạn có thể thực hiện như sau. Chỉ cần trang trí các tài sản trong câu hỏi với các công cụ chuyển đổi tùy chỉnh.

[JsonObject(MemberSerialization.OptIn)] 
public class MyClass 
{ 
    [JsonProperty(PropertyName = "creation_date")] 
    [JsonConverter(typeof(UnixDateTimeConverter))] 
    public DateTime CreationDate { get; set; } 
} 

JSON.NET cung cấp hầu hết các hệ thống ống nước. Chỉ xuất phát từ bộ chuyển đổi cơ sở.

public class UnixDateTimeConverter : DateTimeConverterBase 
{ 
    public override void WriteJson(JsonWriter writer, object value, 
            JsonSerializer serializer) 
    { ...} 

    public override void WriteJson(JsonWriter writer, object value, 
            JsonSerializer serializer) 
    { ... } 
} 

Tất cả những gì bạn phải làm là triển khai phương thức ReadJson (deserialization) và WriteJson (serialization).

Bạn có thể tìm thấy một ví dụ hoàn chỉnh ở đây:

Writing a custom Json.NET DateTime Converter

Đối với vấn đề cụ thể của bạn, bạn cần một chút kiểm soát nhiều hơn. Hãy thử các loại sau đây của chuyển đổi:

public class Contact 
{ 
    private List<Address> _addresses = new List<Address>();  
    public IEnumerable<Address> Addresses { get { return _addresses; } 
} 

public class ContactConverter : CustomCreationConverter<Contact> 
{ 
    public override Contact Create(Type objectType) 
    { 
     return new Contact(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object 
     existingValue, JsonSerializer serializer) 
    { 
     var mappedObj = new Contact(); 

     // Parse JSON data here 
     // ... 

     return mappedObj; 
    } 
} 

Sử dụng một bộ chuyển đổi tùy chỉnh như một ở trên, bạn có thể phân tích các dữ liệu JSON mình và soạn đối tượng Contact (s) như bạn xin vui lòng.

tôi sửa đổi một ví dụ tôi tìm thấy ở đây:

JSON.NET Custom Converters–A Quick Tour

Trong trường hợp này bạn cần phải vượt qua bộ chuyển đổi tùy chỉnh khi desearilizing.

Contact contact = 
    JsonConvert.DeserializeObject<Contact>(json, new ContactConverter()); 
+0

Cảm ơn bạn đã nhập kỹ lưỡng. Từ ví dụ của bạn, tôi nhận được nó làm việc và đăng kết quả cuối cùng của tôi. – angularsen

+0

Nếu bạn downvote ít nhất là bình luận tại sao ... không nhấn và chạy –

+0

Cảm ơn bạn đã liên kết. :) –

5

Dựa trên Christophe Geers 'answer, đây là những gì tôi đã kết thúc.

  1. Tạo trình chuyển đổi JSON tùy chỉnh để luôn phân tích JSON thành mảng. Nếu JSON là một đối tượng không phải mảng, sau đó deserialize đối tượng và bọc nó trong một mảng.

  2. Đánh dấu thuộc tính tương ứng bằng thuộc tính chuyển đổi tùy chỉnh.

Tuỳ chỉnh chuyển đổi

public class JsonToArrayConverter<T> : CustomCreationConverter<T[]> 
{ 
    public override T[] Create(Type objectType) 
    { 
     // Default value is an empty array. 
     return new T[0]; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object 
     existingValue, JsonSerializer serializer) 
    { 

     if (reader.TokenType == JsonToken.StartArray) 
     { 
      // JSON object was an array, so just deserialize it as usual. 
      object result = serializer.Deserialize(reader, objectType); 
      return result; 
     } 
     else 
     { 
      // JSON object was not an arry, so deserialize the object 
      // and wrap it in an array. 
      var resultObject = serializer.Deserialize<T>(reader); 
      return new T[] {resultObject}; 
     } 
    } 
} 

cấu trúc dữ liệu cho các ví dụ câu hỏi

public class Organisation 
{ 
    public Contacts contacts; 
} 

public class Address 
{ 
    public string id; 
    public string street; 
    public string city; 
    public string type; 
    public string zip; 
    public string country; 
} 

public class Contacts 
{ 
    // Tell JSON.net to use the custom converter for this property. 
    [JsonConverter(typeof(JsonToArrayConverter<Address>))] 
    public Address[] address; 
} 
1

Lưu ý: Thay vì sử dụng một CustomCreationConverter, bạn chỉ có thể sử dụng một bộ chuyển đổi thông thường. Ví dụ: tôi sử dụng một cái gì đó như thế này:

public class SingleToArrayConverter<T> : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var items = (IEnumerable<T>)value; 
     if (value == null || !items.Any()) 
     { 
      writer.WriteNull(); 
     } 
     else if (items.Count() == 1) 
     { 
      serializer.Serialize(writer, items.ElementAt(0)); 
     } 
     else 
     { 
      serializer.Serialize(writer, items); 
     } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (!CanConvert(objectType)) 
     { 
      throw new NotSupportedException(); 
     } 

     if (reader.TokenType == JsonToken.Null) 
     { 
      reader.Skip(); 
      return null; 
     } 
     else if (reader.TokenType == JsonToken.StartObject) 
     { 
      return new T[] { serializer.Deserialize<T>(reader) }; 
     } 
     else 
     { 
      return serializer.Deserialize<T[]>(reader); 
     } 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(IEnumerable<T>); 
    } 
} 
Các vấn đề liên quan