2014-09-18 4 views
0

Я хочу десериализировать комплекс и, скажем, неплохо построенный json. Этот код, который я написал, не десериализует объект, свойство MovieInfo равно null. Вы можете найти пример json в коде. Я хочу избежать использования JObject.Parse и dynamic объектов. Что мне здесь не хватает?Deserializing complex Json objects

using System.Collections.Generic; 
using Newtonsoft.Json; 

namespace ComplexJsonExample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string jsonInText = @" 
      { 
       ""movies"" : [ 
        { 
         ""Harry Potter"" : [ 
          { ""rating"": ""great""}, 
          { ""rating"": ""horrible""} 
         ] 
        }, 
        { 
         ""Guardians of the galaxy"" : [ 
          { ""rating"": ""cool""}, 
          { ""rating"": ""awesome""} 
         ] 
        } 
       ] 
      } 
      "; 

      var movieList = JsonConvert.DeserializeObject<MovieList>(jsonInText); 
     } 
    } 

    public class MovieList 
    { 
     [JsonProperty("movies")] 
     public IList<Movie> Movies { get; set; } 
    } 

    public class Movie 
    { 
     IDictionary<string, IList<MovieRating>> MovieInfo { get; set; } 
    } 

    public class MovieRating 
    { 
     [JsonProperty("rating")] 
     public string Rating { get; set; } 
    } 
} 
+0

Что вам не хватает? Хорошо сформированный json! – Jamiec

+0

Проблема в том, что я не тот, кто создал json, это дается как есть. – boli

+0

Возможно, вы захотите проверить этот вопрос/ответ: http://stackoverflow.com/questions/9452901/cannot-deserialize-json-array-into-type-json-net/9453191#9453191 – Jamiec

ответ

1

это немного некрасиво, но вы можете сделать это следующим образом:

class MovieList 
{ 
    [JsonProperty("movies")] 
    public Movie[] Movies { get; set; } 
} 

class Movie : Dictionary<string, MovieRating[]> 
{ 
} 

class MovieRating 
{ 
    [JsonProperty("rating")] 
    public string Rating { get; set; } 
} 

Это странно, что фильм представляет собой словарь только один ключ (его название), но она соответствует структуре JSON. Вы можете всегда сопоставить его с чем-то более разумным после десериализации.

+0

Что я пробовал раньше, так это объявить' '' Словарь '' 'поле в классе Movie. Спасибо за решение. – boli

1

Я считаю это немного рубить, но это работает, и десериализует вашу строку JSON в формат вы требовали:

class MovieConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Movie); 
    } 

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

     var movie = new Movie(){ 
      MovieInfo = new Dictionary<string,IList<MovieRating>>() 
     }; 

     while (reader.Read() && reader.Value != null) 
     {     
      var name = (string)reader.Value; 

      reader.Read(); 

      var ratings = ((JArray)serializer.Deserialize(reader)).Values<string>("rating"); 

      movie.MovieInfo.Add(name, ratings.Select(r => new MovieRating(){ Rating = r}).ToList()); 
     } 
     return movie; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

я должен сделать два изменения в ваших исходных объектов, Сначала я сделал аксессор для MovieInfo публики, чтобы я мог получить доступ к нему, а второй, чтобы добавить JsonConverterAttribute:

[JsonConverter(typeof(MovieConverter))] 
public class Movie 
{ 
    public IDictionary<string, IList<MovieRating>> MovieInfo { get; set; } 
}