2013-04-03 3 views
9

Учитывая следующие JSON:Deserialize массив пар ключ-значение, используя Json.NET

[ {"id":"123", ... "data":[{"key1":"val1"}, {"key2":"val2"}], ...}, ... ] 

, что является частью большого дерева, как я могу десериализовать «данные» собственность в:

List<MyCustomClass> Data { get; set; } 

или

List<KeyValuePair> Data { get; set; } 

или

Dictionary<string, string> Data { get; set; } 

используя Json.NET? Любая версия будет делать (я предпочитаю List of MyCustomClass, хотя). У меня уже есть класс, который содержит другие свойства, например:

public class SomeData 
{ 
    [JsonProperty("_id")] 
    public string Id { get; set; } 
    ... 
    public List<MyCustomClass> Data { get; set; } 
} 

где «MyCustomClass» будет включать в себя только два свойства (Key и Value). Я заметил, что есть класс KeyValuePairConverter, который звучит так, будто он будет делать то, что мне нужно, но я не смог найти пример о том, как его использовать. Благодарю.

ответ

16

Самый простой способ Deserialize массив пар ключ-значение для IDictionary<string, string>:

 

public class SomeData 
{ 
    public string Id { get; set; } 

    public IEnumerable<IDictionary<string, string>> Data { get; set; } 
} 

private static void Main(string[] args) 
{ 
    var json = "{ \"id\": \"123\", \"data\": [ { \"key1\": \"val1\" }, { \"key2\" : \"val2\" } ] }"; 

    var obj = JsonConvert.DeserializeObject<SomeData>(json); 
} 
 

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

 

public class SomeData2 
{ 
    public string Id { get; set; } 

    public List<SomeDataPair> Data { get; set; } 
} 

public class SomeDataPair 
{ 
    public string Key { get; set; } 

    public string Value { get; set; } 
} 

private static void Main(string[] args) 
{ 
    var json = "{ \"id\": \"123\", \"data\": [ { \"key1\": \"val1\" }, { \"key2\" : \"val2\" } ] }"; 

    var rawObj = JObject.Parse(json); 

    var obj2 = new SomeData2 
    { 
     Id = (string)rawObj["id"], 
     Data = new List<SomeDataPair>() 
    }; 

    foreach (var item in rawObj["data"]) 
    { 
     foreach (var prop in item) 
     { 
      var property = prop as JProperty; 

      if (property != null) 
      { 
       obj2.Data.Add(new SomeDataPair() { Key = property.Name, Value = property.Value.ToString() }); 
      } 

     } 
    } 
} 
 

Смотрите, что я так понимаю, что Value is string и я вызываю метод ToString(), может быть другой сложный класс.

+1

Список словарей работ; Спасибо за это. Поскольку изменение, которое я пытаюсь сделать, является частью более крупной библиотеки, я пытаюсь избежать необходимости писать пользовательскую инициализацию объекта. Я занимаюсь написанием пользовательского конвертера для своего класса (SomeData2 в вашем примере). Если я не могу заставить его работать, я буду использовать метод List of Dictionary. Благодарю. – pbz

+0

Спасибо за этот ответ. У меня был такой же json с массивом с ключевым значением. Я просто использовал public IEnumerable Data {get; задавать; } для этого поля и работал как шарм. весь мой json был разобран отлично! .. – maths

1

я в конечном итоге делает это:

[JsonConverter(typeof(MyCustomClassConverter))] 
public class MyCustomClass 
{ 
    internal class MyCustomClassConverter : JsonConverter 
    { 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JObject jObject = JObject.Load(reader); 

     foreach (var prop in jObject) 
     { 
     return new MyCustomClass { Key = prop.Key, Value = prop.Value.ToString() }; 
     } 

     return null; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof(MyCustomClass).IsAssignableFrom(objectType); 
    } 
    } 

    public string Key { get; set; } 
    public string Value { get; set; } 
} 
Смежные вопросы