Как я могу десериализовать JSON для простого словаря в ASP.NET?

У меня есть простой список ключей / значений в JSON, который отправляется обратно на ASP.NET через POST. Пример:

{ "key1": "value1", "key2": "value2"} 

Я НЕ ПЫТАЮСЬ ЗАСТРАХОВАТЬ В СИЛЬНО ТИПОВЫЕ ОБЪЕКТЫ .NET

Мне просто нужен простой старый словарь (Of String, String) или какой-то эквивалент (хеш-таблица, словарь (Of String, Object), старая школа StringDictionary – ад, для меня будет работать 2-мерный массив строк.

Я могу использовать все, что доступно в ASP.NET 3.5, а также популярный Json.NET (который я уже использую для сериализации для клиента).

По-видимому, ни одна из этих JSON-библиотек не обладает очевидной способностью «лба-шлепать» очевидными возможностями – они полностью сосредоточены на десериализации на основе рефлексии через сильные контракты.

Есть идеи?

Ограничения:

  1. Я не хочу реализовывать собственный анализатор JSON
  2. Не удается использовать ASP.NET 4.0
  3. Предпочитаете держаться подальше от старого, устаревшего classа ASP.NET для JSON

Json.NET делает это …

 string json = @"{""key1"":""value1"",""key2"":""value2""}"; var values = JsonConvert.DeserializeObject>(json); 

Дополнительные примеры: Сериализация коллекций с помощью Json.NET

Я обнаружил, что .NET имеет встроенный способ передачи строки JSON в Dictionary через тип System.Web.Extensions сборке 3.5 System.Web.Extensions . Используйте метод DeserializeObject(String) .

Я наткнулся на это, сделав сообщение ajax (через jquery) типа контента «application / json» на статический метод .NET-страницы и увидел, что метод (который имел единственный параметр типа Object ), магически получивший этот Словарь.

Для тех, кто ищет в Интернете и наткнулся на этот пост, я написал сообщение в блоге о том, как использовать class JavaScriptSerializer.

Подробнее … http://procbits.com/2011/04/21/quick-json-serializationdeserialization-in-c/

Вот пример:

 var json = "{\"id\":\"13\", \"value\": true}"; var jss = new JavaScriptSerializer(); var table = jss.Deserialize(json); Console.WriteLine(table["id"]); Console.WriteLine(table["value"]); 

Пытался не использовать какую-либо внешнюю реализацию JSON, поэтому я deserialised следующим образом:

 string json = "{\"id\":\"13\", \"value\": true}"; var serializer = new JavaScriptSerializer(); //using System.Web.Script.Serialization; Dictionary values = serializer.Deserialize>(json); 

У меня была та же проблема, поэтому я написал это сам. Это решение отличается от других ответов, поскольку оно может десериализоваться на нескольких уровнях.

Просто отправьте строку JSON в функцию deserializeToDictionary, она вернет не строго типизированный Dictionary object.

Старый код

 private Dictionary deserializeToDictionary(string jo) { var values = JsonConvert.DeserializeObject>(jo); var values2 = new Dictionary(); foreach (KeyValuePair d in values) { // if (d.Value.GetType().FullName.Contains("Newtonsoft.Json.Linq.JObject")) if (d.Value is JObject) { values2.Add(d.Key, deserializeToDictionary(d.Value.ToString())); } else { values2.Add(d.Key, d.Value); } } return values2; } 

Пример: это вернет Dictionary объекта ответа JSON на Facebook.

Контрольная работа

 private void button1_Click(object sender, EventArgs e) { string responsestring = "{\"id\":\"721055828\",\"name\":\"Dasun Sameera Weerasinghe\",\"first_name\":\"Dasun\",\"middle_name\":\"Sameera\",\"last_name\":\"Weerasinghe\",\"username\":\"dasun\",\"gender\":\"male\",\"locale\":\"en_US\", hometown: {id: \"108388329191258\", name: \"Moratuwa, Sri Lanka\",}}"; Dictionary values = deserializeToDictionary(responsestring); } 

Примечание: родной город далее deserilize в Dictionary object.

Обновить

Мой старый ответ отлично работает, если в строке JSON нет массива. Этот еще один десериализуется в List если элемент является массивом.

Просто отправьте строку JSON в функцию deserializeToDictionaryOrList, она вернет не строго типизированный Dictionary object или List .

 private static object deserializeToDictionaryOrList(string jo,bool isArray=false) { if (!isArray) { isArray = jo.Substring(0, 1) == "["; } if (!isArray) { var values = JsonConvert.DeserializeObject>(jo); var values2 = new Dictionary(); foreach (KeyValuePair d in values) { if (d.Value is JObject) { values2.Add(d.Key, deserializeToDictionary(d.Value.ToString())); } else if (d.Value is JArray) { values2.Add(d.Key, deserializeToDictionary(d.Value.ToString(), true)); } else { values2.Add(d.Key, d.Value); } } return values2; }else { var values = JsonConvert.DeserializeObject>(jo); var values2 = new List(); foreach (var d in values) { if (d is JObject) { values2.Add(deserializeToDictionary(d.ToString())); } else if (d is JArray) { values2.Add(deserializeToDictionary(d.ToString(), true)); } else { values2.Add(d); } } return values2; } } 

Если вы после легкого, не-добавленного-ссылочного типа подхода, возможно, этот бит кода, который я только что написал, будет работать (я не могу гарантировать 100% надежность).

 using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; public Dictionary ParseJSON(string json) { int end; return ParseJSON(json, 0, out end); } private Dictionary ParseJSON(string json, int start, out int end) { Dictionary dict = new Dictionary(); bool escbegin = false; bool escend = false; bool inquotes = false; string key = null; int cend; StringBuilder sb = new StringBuilder(); Dictionary child = null; List arraylist = null; Regex regex = new Regex(@"\\u([0-9a-z]{4})", RegexOptions.IgnoreCase); int autoKey = 0; for (int i = start; i < json.Length; i++) { char c = json[i]; if (c == '\\') escbegin = !escbegin; if (!escbegin) { if (c == '"') { inquotes = !inquotes; if (!inquotes && arraylist != null) { arraylist.Add(DecodeString(regex, sb.ToString())); sb.Length = 0; } continue; } if (!inquotes) { switch (c) { case '{': if (i != start) { child = ParseJSON(json, i, out cend); if (arraylist != null) arraylist.Add(child); else { dict.Add(key, child); key = null; } i = cend; } continue; case '}': end = i; if (key != null) { if (arraylist != null) dict.Add(key, arraylist); else dict.Add(key, DecodeString(regex, sb.ToString())); } return dict; case '[': arraylist = new List(); continue; case ']': if (key == null) { key = "array" + autoKey.ToString(); autoKey++; } if (arraylist != null && sb.Length > 0) { arraylist.Add(sb.ToString()); sb.Length = 0; } dict.Add(key, arraylist); arraylist = null; key = null; continue; case ',': if (arraylist == null && key != null) { dict.Add(key, DecodeString(regex, sb.ToString())); key = null; sb.Length = 0; } if (arraylist != null && sb.Length > 0) { arraylist.Add(sb.ToString()); sb.Length = 0; } continue; case ':': key = DecodeString(regex, sb.ToString()); sb.Length = 0; continue; } } } sb.Append(c); if (escend) escbegin = false; if (escbegin) escend = true; else escend = false; } end = json.Length - 1; return dict; //theoretically shouldn't ever get here } private string DecodeString(Regex regex, string str) { return Regex.Unescape(regex.Replace(str, match => char.ConvertFromUtf32(Int32.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.HexNumber)))); } 

[Я понимаю, что это нарушает OP Limitation # 1, но технически вы этого не пишете, я сделал]

Мне просто нужно было разобрать вложенный словарь, например

 { "x": { "a": 1, "b": 2, "c": 3 } } 

где JsonConvert.DeserializeObject не помогает. Я нашел следующий подход:

 var dict = JObject.Parse(json).SelectToken("x").ToObject>(); 

SelectToken позволяет вам копать в нужное поле. Вы даже можете указать путь, подобный "xyz" чтобы перейти дальше в объект JSON.

Изменить: это работает, но принятый ответ с использованием Json.NET гораздо более прост. Оставляя это на случай, если кому-то нужен только код BCL.

Это не поддерживается платформой .NET из коробки. Взгляд надзора – не всем нужно десериализовать объекты с именованными свойствами. Поэтому я закончил свой собственный:

  Public Class StringStringDictionary Implements ISerializable Public dict As System.Collections.Generic.Dictionary(Of String, String) Public Sub New() dict = New System.Collections.Generic.Dictionary(Of String, String) End Sub Protected Sub New(info As SerializationInfo, _ context As StreamingContext) dict = New System.Collections.Generic.Dictionary(Of String, String) For Each entry As SerializationEntry In info dict.Add(entry.Name, DirectCast(entry.Value, String)) Next End Sub Public Sub GetObjectData(info As SerializationInfo, context As StreamingContext) Implements ISerializable.GetObjectData For Each key As String in dict.Keys info.AddValue(key, dict.Item(key)) Next End Sub End Class 

Вызывается с:

 string MyJsonString = "{ \"key1\": \"value1\", \"key2\": \"value2\"}"; System.Runtime.Serialization.Json.DataContractJsonSerializer dcjs = new System.Runtime.Serialization.Json.DataContractJsonSerializer( typeof(StringStringDictionary)); System.IO.MemoryStream ms = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(MyJsonString)); StringStringDictionary myfields = (StringStringDictionary)dcjs.ReadObject(ms); Response.Write("Value of key2: " + myfields.dict["key2"]); 

Извините за сочетание C # и VB.NET …

Я добавил проверку нулевых значений в JSON на другой ответ

У меня была такая же проблема, поэтому я написал это сам. Это решение отличается от других ответов, поскольку оно может десериализоваться на нескольких уровнях.

Просто отправьте json string в функцию deserializeToDictionary, она вернет не строго типизированный Dictionary object.

 private Dictionary deserializeToDictionary(string jo) { var values = JsonConvert.DeserializeObject>(jo); var values2 = new Dictionary(); foreach (KeyValuePair d in values) { if (d.Value != null && d.Value.GetType().FullName.Contains("Newtonsoft.Json.Linq.JObject")) { values2.Add(d.Key, deserializeToDictionary(d.Value.ToString())); } else { values2.Add(d.Key, d.Value); } } return values2; } 

Пример: это вернет Dictionary объекта ответа JSON на Facebook.

 private void button1_Click(object sender, EventArgs e) { string responsestring = "{\"id\":\"721055828\",\"name\":\"Dasun Sameera Weerasinghe\",\"first_name\":\"Dasun\",\"middle_name\":\"Sameera\",\"last_name\":\"Weerasinghe\",\"username\":\"dasun\",\"gender\":\"male\",\"locale\":\"en_US\", hometown: {id: \"108388329191258\", name: \"Moratuwa, Sri Lanka\",}}"; Dictionary values = deserializeToDictionary(responsestring); } 

Примечание: родной город далее десериализуется в объект Dictionary .

Я добавил код, представленный jSnake04 и Dasun. Я добавил код для создания списков объектов из экземпляров JArray . Он имеет двухстороннюю рекурсию, но поскольку он функционирует на фиксированной конечной модели дерева, нет риска переполнения стека, если данные не массивны.

 ///  /// Deserialize the given JSON string data () into a /// dictionary. ///  /// JSON string. /// Deserialized dictionary. private IDictionary DeserializeData(string data) { var values = JsonConvert.DeserializeObject>(data); return DeserializeData(values); } ///  /// Deserialize the given JSON object () into a dictionary. ///  /// JSON object. /// Deserialized dictionary. private IDictionary DeserializeData(JObject data) { var dict = data.ToObject>(); return DeserializeData(dict); } ///  /// Deserialize any elements of the given data dictionary () /// that are JSON object or JSON arrays into dictionaries or lists respectively. ///  /// Data dictionary. /// Deserialized dictionary. private IDictionary DeserializeData(IDictionary data) { foreach (var key in data.Keys.ToArray()) { var value = data[key]; if (value is JObject) data[key] = DeserializeData(value as JObject); if (value is JArray) data[key] = DeserializeData(value as JArray); } return data; } ///  /// Deserialize the given JSON array () into a list. ///  /// Data dictionary. /// Deserialized list. private IList DeserializeData(JArray data) { var list = data.ToObject>(); for (int i = 0; i < list.Count; i++) { var value = list[i]; if (value is JObject) list[i] = DeserializeData(value as JObject); if (value is JArray) list[i] = DeserializeData(value as JArray); } return list; } 

Марк Рендл опубликовал это как комментарий , я хотел опубликовать его как ответ, так как это единственное решение, которое до сих пор работало, чтобы вернуть успех, а коды ошибок json – результат ответа Google reCaptcha.

 string jsonReponseString= wClient.DownloadString(requestUrl); IDictionary dict = new JavaScriptSerializer().DeserializeObject(jsonReponseString) as IDictionary; 

Еще раз спасибо, Марк!

Кажется, что все эти ответы здесь предполагают, что вы можете получить эту маленькую строку из более крупного объекта … для людей, которые хотят просто дезерализовать большой объект с таким словарем где-то внутри сопоставления и кто использует System.Runtime.Serialization.Json Система System.Runtime.Serialization.Json DataContract, вот решение:

Ответ на gis.stackexchange.com имел эту интересную ссылку . Мне пришлось восстановить его с помощью archive.org, но он предлагает довольно совершенное решение: собственный class IDataContractSurrogate в котором вы реализуете именно ваши собственные типы. Я смог легко ее расширить.

Тем не менее, я сделал кучу изменений. Поскольку исходный источник больше не доступен, я выведу весь class здесь:

 using System; using System.CodeDom; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Text; namespace JsonTools { ///  /// Allows using Dictionary<String,String> and Dictionary<String,Boolean> types, and any others you'd like to add. /// Source: https://web.archive.org/web/20100317222656/my6solutions.com/post/2009/06/30/DataContractSerializer-DataContractJsonSerializer-JavaScriptSerializer-XmlSerializer-for-serialization.aspx ///  public class JsonSurrogate : IDataContractSurrogate { ///  /// Deserialize an object with added support for the types defined in this class. ///  /// Contract class /// JSON String /// Text encoding /// The deserialized object of type T public static T Deserialize(String json, Encoding encoding) { if (encoding == null) encoding = new UTF8Encoding(false); DataContractJsonSerializer deserializer = new DataContractJsonSerializer( typeof(T), new Type[0], int.MaxValue, true, new JsonSurrogate(), false); using (MemoryStream stream = new MemoryStream(encoding.GetBytes(json))) { T result = (T)deserializer.ReadObject(stream); return result; } } // make sure all values in this are classes implementing JsonSurrogateObject. private static Dictionary KnownTypes = new Dictionary() { {typeof(Dictionary), typeof(SSDictionary)}, {typeof(Dictionary), typeof(SBDictionary)} }; #region Implemented surrogate dictionary classes [Serializable] public class SSDictionary : SurrogateDictionary { public SSDictionary() : base() {} protected SSDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {} } [Serializable] public class SBDictionary : SurrogateDictionary { public SBDictionary() : base() {} protected SBDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {} } #endregion /// Small interface to easily extract the final value from the object. public interface JsonSurrogateObject { Object DeserializedObject { get; } } ///  /// Class for deserializing any simple dictionary types with a string as key. ///  /// Any simple type that will be deserialized correctly. [Serializable] public abstract class SurrogateDictionary : ISerializable, JsonSurrogateObject { public Object DeserializedObject { get { return dict; } } private Dictionary dict; public SurrogateDictionary() { dict = new Dictionary(); } // deserialize protected SurrogateDictionary(SerializationInfo info, StreamingContext context) { dict = new Dictionary(); foreach (SerializationEntry entry in info) { // This cast will only work for base types, of course. dict.Add(entry.Name, (T)entry.Value); } } // serialize public void GetObjectData(SerializationInfo info, StreamingContext context) { foreach (String key in dict.Keys) { info.AddValue(key, dict[key]); } } } ///  /// Uses the KnownTypes dictionary to get the surrogate classes. ///  ///  ///  public Type GetDataContractType(Type type) { Type returnType; if (KnownTypes.TryGetValue(type, out returnType)) { return returnType; } return type; } public object GetObjectToSerialize(object obj, Type targetType) { throw new NotImplementedException(); } ///  /// Gets the object out of the surrogate datacontract object. This function is the reason all surrogate objects need to implement the JsonSurrogateObject class. ///  /// Result of the deserialization /// Expected target type of the deserialization ///  public object GetDeserializedObject(object obj, Type targetType) { if (obj is JsonSurrogateObject) { return ((JsonSurrogateObject)obj).DeserializedObject; } return obj; } public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) { return null; } #region not implemented public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) { throw new NotImplementedException(); } public object GetCustomDataToExport(Type clrType, Type dataContractType) { throw new NotImplementedException(); } public void GetKnownCustomDataTypes(Collection customDataTypes) { throw new NotImplementedException(); } public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) { throw new NotImplementedException(); } #endregion } } 

Чтобы добавить к classу новые поддерживаемые типы, вам просто нужно добавить свой class, дать ему правильные конструкторы и функции (посмотрите пример SurrogateDictionary для примера), убедитесь, что он наследует JsonSurrogateObject и добавляет его сопоставление KnownTypes словарь KnownTypes . Включенный SurrogateDictionary может служить основой для любых типов Dictionary где T – любой тип, который десериализуется правильно.

Называть это очень просто:

 MyObjtype newObj = JsonSurrogate.Deserialize(jsonStr, encoding); 

Обратите внимание, что по какой-то причине у этой вещи возникают проблемы с использованием ключевых строк, содержащих пробелы; они просто не присутствовали в финальном списке. Может быть, это просто против json specs, и api, который я звонил, был плохо реализован, заметьте; Не знаю. Во всяком случае, я решил это путем регулярного выражения, заменив их символами подчеркивания в исходных данных json и установив словарь после десериализации.

Основываясь на комментариях выше, попробуйте JsonConvert.DeserializeObject>(json)

 var json = @"{""key1"":1,""key2"":""value2"", ""object1"":{""property1"":""value1"",""property2"":[2,3,4,5,6,7]}}"; var parsedObject = JsonConvert.DeserializeObject>(json); 

похоже, работает даже для сложных объектов и списков.

Я только что реализовал это в RestSharp . Этот пост был полезен для меня.

Помимо кода в ссылке, вот мой код. Теперь я получаю Dictionary результатов, когда я делаю что-то вроде этого:

 var jsonClient = new RestClient(url.Host); jsonClient.AddHandler("application/json", new DynamicJsonDeserializer()); var jsonRequest = new RestRequest(url.Query, Method.GET); Dictionary response = jsonClient.Execute(jsonRequest).Data.ToObject>(); 

Помните о том, какой JSON вы ожидаете – в моем случае я извлекал один объект с несколькими свойствами. В прикрепленной ссылке автор извлекал список.

Мой подход напрямую десериализуется в IDictionary, без JObject или ExpandObject между ними. В коде используется конвертер, который в основном копируется из classа ExpandoObjectConverter, найденного в исходном коде JSON.NET, но с использованием IDictionary вместо ExpandoObject.

Применение:

 var settings = new JsonSerializerSettings() { Converters = { new DictionaryConverter() }, }; var result = JsonConvert.DeserializeObject>(json, settings); 

Код:

 // based on ExpandoObjectConverter, but using arrays instead of IList, to behave similar to System.Web.Script.Serialization.JavaScriptSerializer public class DictionaryConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return ReadValue(reader); } public override bool CanConvert(Type objectType) { return (objectType == typeof(IDictionary)); } public override bool CanWrite { get { return false; } } private object ReadValue(JsonReader reader) { while (reader.TokenType == JsonToken.Comment) { if (!reader.Read()) throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary."); } switch (reader.TokenType) { case JsonToken.StartObject: return ReadObject(reader); case JsonToken.StartArray: return ReadList(reader); default: if (IsPrimitiveToken(reader.TokenType)) return reader.Value; throw JsonSerializationExceptionCreate(reader, string.Format(CultureInfo.InvariantCulture, "Unexpected token when converting IDictionary: {0}", reader.TokenType)); } } private object ReadList(JsonReader reader) { List list = new List(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.Comment: break; default: object v = ReadValue(reader); list.Add(v); break; case JsonToken.EndArray: return list; } } throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary."); } private object ReadObject(JsonReader reader) { IDictionary dictionary = new Dictionary(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: string propertyName = reader.Value.ToString(); if (!reader.Read()) throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary."); object v = ReadValue(reader); dictionary[propertyName] = v; break; case JsonToken.Comment: break; case JsonToken.EndObject: return dictionary; } } throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary."); } //based on internal Newtonsoft.Json.JsonReader.IsPrimitiveToken internal static bool IsPrimitiveToken(JsonToken token) { switch (token) { case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Undefined: case JsonToken.Null: case JsonToken.Date: case JsonToken.Bytes: return true; default: return false; } } // based on internal Newtonsoft.Json.JsonSerializationException.Create private static JsonSerializationException JsonSerializationExceptionCreate(JsonReader reader, string message, Exception ex = null) { return JsonSerializationExceptionCreate(reader as IJsonLineInfo, reader.Path, message, ex); } // based on internal Newtonsoft.Json.JsonSerializationException.Create private static JsonSerializationException JsonSerializationExceptionCreate(IJsonLineInfo lineInfo, string path, string message, Exception ex) { message = JsonPositionFormatMessage(lineInfo, path, message); return new JsonSerializationException(message, ex); } // based on internal Newtonsoft.Json.JsonPosition.FormatMessage internal static string JsonPositionFormatMessage(IJsonLineInfo lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine)) { message = message.Trim(); if (!message.EndsWith(".", StringComparison.Ordinal)) message += "."; message += " "; } message += string.Format(CultureInfo.InvariantCulture, "Path '{0}'", path); if (lineInfo != null && lineInfo.HasLineInfo()) message += string.Format(CultureInfo.InvariantCulture, ", line {0}, position {1}", lineInfo.LineNumber, lineInfo.LinePosition); message += "."; return message; } } 

Annoyingly enough, if you want to use the default model binders, it looks like you will have to use numerical index values like a form POST.

See the following excerpt from this article http://msdn.microsoft.com/en-us/magazine/hh781022.aspx :

Though it’s somewhat counterintuitive, JSON requests have the same requirements—they, too, must adhere to the form post naming syntax. Take, for example, the JSON payload for the previous UnitPrice collection. The pure JSON array syntax for this data would be represented as:

 [ { "Code": "USD", "Amount": 100.00 }, { "Code": "EUR", "Amount": 73.64 } ] 

However, the default value providers and model binders require the data to be represented as a JSON form post:

 { "UnitPrice[0].Code": "USD", "UnitPrice[0].Amount": 100.00, "UnitPrice[1].Code": "EUR", "UnitPrice[1].Amount": 73.64 } 

The complex object collection scenario is perhaps one of the most widely problematic scenarios that developers run into because the syntax isn’t necessarily evident to all developers. However, once you learn the relatively simple syntax for posting complex collections, these scenarios become much easier to deal with.

You could use Tiny-JSON

 string json = "{\"key1\":\"value1\", \"key2\":\"value2\"}"; IDictionary dict = Tiny.Json.Decode>(json); 

A bit late to the game, but non of the above solutions pointed me in the direction of a pure and simple .NET, no json.net solution. So here it is, ended up being very simple. Below a full running example of how it is done with standard .NET Json serialization, the example has dictionary both in the root object and in the child objects.

The golden bullet is this cat, parse the settings as second parameter to the serializer:

 DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings(); settings.UseSimpleDictionaryFormat = true; 

Полный код ниже:

 using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; namespace Kipon.dk { public class JsonTest { public const string EXAMPLE = @"{ ""id"": ""some id"", ""children"": { ""f1"": { ""name"": ""name 1"", ""subs"": { ""1"": { ""name"": ""first sub"" }, ""2"": { ""name"": ""second sub"" } } }, ""f2"": { ""name"": ""name 2"", ""subs"": { ""37"": { ""name"": ""is 37 in key""} } } } } "; [DataContract] public class Root { [DataMember(Name ="id")] public string Id { get; set; } [DataMember(Name = "children")] public Dictionary Children { get; set; } } [DataContract] public class Child { [DataMember(Name = "name")] public string Name { get; set; } [DataMember(Name = "subs")] public Dictionary Subs { get; set; } } [DataContract] public class Sub { [DataMember(Name = "name")] public string Name { get; set; } } public static void Test() { var array = System.Text.Encoding.UTF8.GetBytes(EXAMPLE); using (var mem = new System.IO.MemoryStream(array)) { mem.Seek(0, System.IO.SeekOrigin.Begin); DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings(); settings.UseSimpleDictionaryFormat = true; var ser = new DataContractJsonSerializer(typeof(Root), settings); var data = (Root)ser.ReadObject(mem); Console.WriteLine(data.Id); foreach (var childKey in data.Children.Keys) { var child = data.Children[childKey]; Console.WriteLine(" Child: " + childKey + " " + child.Name); foreach (var subKey in child.Subs.Keys) { var sub = child.Subs[subKey]; Console.WriteLine(" Sub: " + subKey + " " + sub.Name); } } } } } } 

I would suggest using System.Runtime.Serialization.Json that is part of .NET 4.5.

 [DataContract] public class Foo { [DataMember(Name = "data")] public Dictionary Data { get; set; } } 

Then use it like this:

 var serializer = new DataContractJsonSerializer(typeof(List)); var jsonParams = @"{""data"": [{""Key"":""foo"",""Value"":""bar""}] }"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonParams)); var obj = serializer.ReadObject(stream); Console.WriteLine(obj); 
  • Как преобразовать массив Json в список объектов в c #
  • Что такое эквивалент JSON.NET XPath, SelectNodes XML, SelectSingleNode?
  • JToken: получить исходное / оригинальное значение JSON
  • Как я могу разбирать JSON с C #?
  • Линейная сериализация и де-сериализация
  • Как изменить имена свойств при сериализации с помощью Json.net?
  • Сериализация типа Json.Net с полиморфным дочерним объектом
  • Дезаминирование гетерогенного массива JSON в ковариантный список с использованием JSON.NET
  • Как показать «вставить class Json» в visual studio 2012, нажав на «Специальная вставка»?
  • Использование преобразователей Json.NET для десериализации свойств
  • Как реализовать пользовательский JsonConverter в JSON.NET для десериализации списка объектов базового classа?
  • Давайте будем гением компьютера.