For example, you can deserialize into JObject , and then convert the data manually:
var obj = JObject.Parse(json); var rates_scores_stats = ((JArray)obj["rates_scores_stats"]).ToDictionary(entry => (int)entry["name"], entry => (int)entry["value"]); var rates_statuses_stats = ((JArray)obj["rates_statuses_stats"]).ToDictionary(entry => (string)entry["name"], entry => (int)entry["value"]); var result = new MyClass() { rates_scores_stats = rates_scores_stats, rates_statuses_stats = rates_statuses_stats };
The alternative answer is here . By slightly modifying it, you can get a less “manual” solution.
Create a separate converter (damned and modified from the response by reference):
public class JsonGenericDictionaryOrArrayConverter : JsonConverter { // поскольку у вас в JSON'е не key/value, а name/value, нужен специальный класс // для десериализации одного элемента массива class NameValuePair<N, V> { public N name { get; set; } public V value { get; set; } } public override bool CanConvert(Type objectType) { return GetDictionaryKeyValueTypes(objectType).Count() == 1; } public override bool CanWrite { get { return false; } } object ReadJsonGeneric<TKey, TValue>( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var tokenType = reader.TokenType; var dict = existingValue as IDictionary<TKey, TValue>; if (dict == null) { var contract = serializer.ContractResolver.ResolveContract(objectType); dict = (IDictionary<TKey, TValue>)contract.DefaultCreator(); } if (tokenType == JsonToken.StartArray) { var pairs = new JsonSerializer() .Deserialize<NameValuePair<TKey, TValue>[]>(reader); if (pairs == null) return existingValue; foreach (var pair in pairs) dict.Add(pair.name, pair.value); } else if (tokenType == JsonToken.StartObject) { // Using "Populate()" avoids infinite recursion. // https://github.com/JamesNK/Newtonsoft.Json/blob/ // ee170dc5510bb3ffd35fc1b0d986f34e33c51ab9/Src/Newtonsoft.Json/Converters/ // CustomCreationConverter.cs serializer.Populate(reader, dict); } return dict; } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Throws an exception if not exactly one. var keyValueTypes = GetDictionaryKeyValueTypes(objectType).Single(); var method = GetType().GetMethod( "ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); var genericMethod = method.MakeGenericMethod( new[] { keyValueTypes.Key, keyValueTypes.Value }); return genericMethod.Invoke( this, new object[] { reader, objectType, existingValue, serializer }); } public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer) { throw new NotSupportedException(); } static IEnumerable<KeyValuePair<Type, Type>> GetDictionaryKeyValueTypes(Type type) { foreach (Type intType in GetInterfacesAndSelf(type)) { if (intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) { var args = intType.GetGenericArguments(); if (args.Length == 2) yield return new KeyValuePair<Type, Type>(args[0], args[1]); } } } static IEnumerable<Type> GetInterfacesAndSelf(Type type) { if (type == null) throw new ArgumentNullException(); if (type.IsInterface) return new[] { type }.Concat(type.GetInterfaces()); else return type.GetInterfaces(); } }
Having this auxiliary class, you can deserialize just like this:
var settings = new JsonSerializerSettings { Converters = { new JsonGenericDictionaryOrArrayConverter() } }; var result = JsonConvert.DeserializeObject<MyClass>(jsonString, settings);
Update: For a portable library (.NET 4.5.1 + Windows Universal 8.1 + Windows Phone 8.1) I have compiled this:
public class JsonGenericDictionaryOrArrayConverter : JsonConverter { // поскольку у вас в JSON'е не key/value, а name/value, нужен специальный класс // для десериализации одного элемента массива class NameValuePair<N, V> { public N name { get; set; } public V value { get; set; } } public override bool CanConvert(Type objectType) { return GetDictionaryKeyValueTypes(objectType).Count() == 1; } public override bool CanWrite { get { return false; } } public object ReadJsonGeneric<TKey, TValue>( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var tokenType = reader.TokenType; var dict = existingValue as IDictionary<TKey, TValue>; if (dict == null) { var contract = serializer.ContractResolver.ResolveContract(objectType); dict = (IDictionary<TKey, TValue>)contract.DefaultCreator(); } if (tokenType == JsonToken.StartArray) { var pairs = new JsonSerializer() .Deserialize<NameValuePair<TKey, TValue>[]>(reader); if (pairs == null) return existingValue; foreach (var pair in pairs) dict.Add(pair.name, pair.value); } else if (tokenType == JsonToken.StartObject) { // Using "Populate()" avoids infinite recursion. // https://github.com/JamesNK/Newtonsoft.Json/blob/ // ee170dc5510bb3ffd35fc1b0d986f34e33c51ab9/Src/Newtonsoft.Json/Converters/ // CustomCreationConverter.cs serializer.Populate(reader, dict); } return dict; } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Throws an exception if not exactly one. var keyValueTypes = GetDictionaryKeyValueTypes(objectType).Single(); var method = GetType().GetTypeInfo().GetDeclaredMethod("ReadJsonGeneric"); var genericMethod = method.MakeGenericMethod( new[] { keyValueTypes.Key, keyValueTypes.Value }); return genericMethod.Invoke( this, new object[] { reader, objectType, existingValue, serializer }); } public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer) { throw new NotSupportedException(); } static IEnumerable<KeyValuePair<Type, Type>> GetDictionaryKeyValueTypes(Type type) { foreach (Type intType in GetInterfacesAndSelf(type)) { if (intType.GetTypeInfo().IsGenericType && intType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) { var args = intType.GetTypeInfo().GenericTypeArguments; // вроде бы именно GenericTypeArguments, а не Parameters if (args.Length == 2) yield return new KeyValuePair<Type, Type>(args[0], args[1]); } } } static IEnumerable<Type> GetInterfacesAndSelf(Type type) { if (type == null) throw new ArgumentNullException(); if (type.GetTypeInfo().IsInterface) return new[] { type }.Concat(type.GetTypeInfo().ImplementedInterfaces); else return type.GetTypeInfo().ImplementedInterfaces; } }
Newtonsoft.Jsonhas the opportunity to work from json via LINQ - Bulson