2012-04-12 29 views
15

Tôi có một tình huống trong đó JSON được trả lại từ một dịch vụ REST trả về danh sách các đối tượng Phim, tất cả đều được xác định bằng một tấn thông tin. Một vài trường trong đó REST thay đổi kết quả dịch vụ tùy thuộc vào thông tin có sẵn.JSON.net - trường là chuỗi hoặc Danh sách <string>

Ví dụ: Phim luôn có một số ảnh chụp màn hình (hình ảnh), diễn viên và đạo diễn. Tùy thuộc vào bộ phim được đề cập, có thể có một hoặc nhiều hình ảnh, một hoặc nhiều diễn viên và một hoặc nhiều đạo diễn. JSON mẫu cho một vài trường hợp:

{ 
    "title": "Movie title", 
    "images": [ 
     "http://www.url.com/img_0.jpg", 
     "http://www.url.com/img_1.jpg", 
     "http://www.url.com/img_2.jpg", 
     "http://www.url.com/img_3.jpg", 
     "http://www.url.com/img_4.jpg" 
    ], 
    "actors": [ 
     "Steven Berkoff", 
     "Nikolaj Coster-Waldau", 
     "Julie Cox" 
    ], 
    "directors": "Simon Aeby" 
}, 
{ 
    "title": "Another movie", 
    "images": "http://www.url.com/img_1.jpg", 
    "actors": "actor 1" 
    "directors": [ 
     "Justin Bieber", 
     "Justin Timberlake" 
    ] 
} 

Câu hỏi đặt ra là, bằng cách sử dụng JSON.net, làm cách nào để tạo trình chuyển đổi liên quan đến vấn đề này? Tôi đã được cọ rửa internet, nhưng vẫn không tìm thấy một giải pháp.

Một vòng quay khác trên cùng một câu hỏi: Nếu một trường là Danh sách chuỗi hoặc chuỗi đơn giản, làm cách nào để tạo JSON.NET tạo Danh sách theo cách (và nếu chỉ là một chuỗi đơn giản, hãy tạo danh sách thành viên)

EDIT: REST dịch vụ này là ngoài tầm kiểm soát của tôi

+0

đây là dịch vụ của bạn hoặc của bên thứ ba? tôi sẽ đề nghị chỉnh sửa dịch vụ nếu có thể. bởi vì bạn không thể tuần tự hóa fileld thành mảng nếu nó không phải là một mảng trong json. – maxlego

+0

hoặc bạn có thể làm deserialize cho một đối tượng và sau đó ánh xạ chúng vào các lớp học của bạn – jjchiw

+0

Cập nhật các bài viết chung để làm cho mọi thứ rõ ràng hơn –

Trả lời

7

Ok, tôi đã làm nó cho vui, nhưng đừng nghĩ là hữu ích hoặc cách tốt nhất, dù sao ...

Tuyên bố "động" thuộc tính như đối tượng và sau đó tạo ra các phương pháp để có được những tài sản như một cái gì đó như ImagesAsList hoặc ImagesAsString. Tôi đã làm điều đó với phương pháp mở rộng .....

var movies = JsonConvert.DeserializeObject<List<Movie>>(str); 

Lớp

class Movie 
{ 

    [JsonProperty("title")] 
    public string Title { get; set; } 

    [JsonProperty("images")] 
    public object Images { get; set; } 

    [JsonProperty("actors")] 
    public object Actor { get; set; } 

    [JsonProperty("directors")] 
    public object Directors { get; set; } 
} 

Mở rộng phương pháp

static class MovieExtension 
{ 
    public static List<string> ImagesAsList(this Movie m) 
    { 
     var jArray = (m.Images as JArray); 
     if (jArray == null) return null; 

     return jArray.Select(x => x.ToString()).ToList(); 
    } 

    public static string ImagesAsString(this Movie m) 
    { 
     return m.Images as string; 
    } 

} 

EDIT

Sau khi đọc @yamen ý kiến ​​tôi đã làm một số thay đổi như:

var settings = new JsonSerializerSettings(); 
settings.Converters.Add(new MoviesConverter()); 

var movies = JsonConvert.DeserializeObject<List<Movie>>(str, settings); 

Lớp

class Movie 
{ 

    [JsonProperty("title")] 
    public List<string> Title { get; set; } 

    [JsonProperty("images")] 
    public List<string> Images { get; set; } 

    [JsonProperty("actors")] 
    public List<string> Actor { get; set; } 

    [JsonProperty("directors")] 
    public List<string> Directors { get; set; } 
} 

Chuyển đổi

class MoviesConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(string)) || (objectType == typeof(List<string>)) ; 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.StartArray) 
     { 
      var l = new List<string>(); 
      reader.Read(); 
      while (reader.TokenType != JsonToken.EndArray) 
      { 
       l.Add(reader.Value as string); 

       reader.Read(); 
      } 
      return l; 
     } 
     else 
     { 
      return new List<string> { reader.Value as string }; 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     //ToDo here we can decide to write the json as 
     //if only has one attribute output as string if it has more output as list 
    } 
} 
+0

Tôi không nghĩ rằng có bất kỳ cần phải khai báo là đối tượng. Tuyên bố luôn là Danh sách (hoặc Danh sách ) và chỉ cần trả về một phần tử khi JSON cơ bản không phải là mảng. Tuy nhiên, đây là cách API nên hoạt động, do đó, mã hóa hệ thống của bạn theo cách này cũng là việc kiểm chứng trong tương lai. Tiền thưởng thêm là có một lớp ánh xạ rõ ràng. – yamen

+0

Ok, đã thực hiện một số thay đổi và mở rộng Lớp JsonCovert – jjchiw

+0

Câu trả lời này sẽ rất thuận lợi cho câu trả lời được chọn hiện tại của yamen. Nó làm cho việc sử dụng tốt các trình biến đổi JSON.NET và bất kỳ phân tích cú pháp chung nào sẽ vẫn hoạt động miễn là bạn trang trí các đối tượng của mình một cách đúng đắn :) +1 –

3

bạn sẽ không thể để serialise trực tiếp đến một đối tượng, nhưng bạn có thể làm như vậy bằng tay mà không cần nỗ lực quá nhiều. JSON.Net chứa LINQ to JSON. Đầu tiên xác định một phương pháp mà sẽ luôn luôn trả về một danh sách các loại T ngay cả khi JSON cơ bản không phải là một mảng: sử dụng

public List<T> getSingleOrArray<T>(JToken token) 
{ 
    if (token.HasValues) 
    { 
     return token.Select(m => m.ToObject<T>()).ToList(); 
    } 
    else 
    { 
     return new List<T> { token.ToObject<T>() }; 
    } 
} 

mẫu:

JObject m1 = JObject.Parse(@"{ 
""title"": ""Movie title"", 
""images"": [ 
    ""http://www.url.com/img_0.jpg"", 
    ""http://www.url.com/img_1.jpg"" 
], 
""actors"": [ 
    ""Steven Berkoff"", 
    ""Julie Cox"" 
], 
""directors"": ""Simon Aeby"" 
}"); 

JObject m2 = JObject.Parse(@"{ 
""title"": ""Another movie"", 
""images"": ""http://www.url.com/img_1.jpg"", 
""actors"": ""actor 1"", 
""directors"": [ 
    ""Justin Bieber"", 
    ""Justin Timberlake"" 
] 
}"); 

IList<String> m1_directors = getSingleOrArray<string>(m1["directors"]); 
IList<String> m2_directors = getSingleOrArray<string>(m2["directors"]); 

m1_directory là một danh sách với một yếu tố duy nhất, m2_directors là một danh sách có hai phần tử.

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