如何将JSON反序列化为ASP.NET?中的简单字典<string, string>

我有一个简单的JSON键/值列表,通过POST发送回ASP.NET。例子:

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

我并不是要把. NET对象变得冷酷无情

我只需要一个普通的旧字典(of String, String),或者一些等效的(哈希表,字典(字符串,对象),老式的StringDictiony--地狱,一个二维字符串数组对我有用。

我可以使用ASP.NET3.5中可用的任何东西,以及流行的Json.NET(我已经在客户端中使用序列化)。

显然,这些JSON库都没有这种开箱即用的明显能力——它们完全专注于通过强契约进行基于反射的反序列化。

有什么想法吗?

局限性:

  1. 我不想实现自己的JSON解析器
  2. 还不能使用ASP.NET4.0
  3. 希望远离旧的、不建议使用的JSONASP.NET类
895811 次浏览

编辑:这是可行的,但是使用Json.NET的公认答案要简单得多。留下这个以防有人需要仅BCL的代码。

开箱即用的. NET框架不支持它。一个明显的疏忽-不是每个人都需要反序列化为具有命名属性的对象。所以我最终推出了自己的:

VB.NET:

<Serializable()> Public Class StringStringDictionaryImplements ISerializablePublic dict As System.Collections.Generic.Dictionary(Of String, String)Public Sub New()dict = New System.Collections.Generic.Dictionary(Of String, String)End SubProtected Sub New(info As SerializationInfo, _context As StreamingContext)dict = New System.Collections.Generic.Dictionary(Of String, String)For Each entry As SerializationEntry In infodict.Add(entry.Name, DirectCast(entry.Value, String))NextEnd SubPublic Sub GetObjectData(info As SerializationInfo, context As StreamingContext) Implements ISerializable.GetObjectDataFor Each key As String in dict.Keysinfo.AddValue(key, dict.Item(key))NextEnd SubEnd Class

在C#上:

public class StringStringDictionary : ISerializable{public System.Collections.Generic.Dictionary<string, string> dict;public StringStringDictionary(){dict = new System.Collections.Generic.Dictionary<string, string>();}protected StringStringDictionary(SerializationInfo info, StreamingContext context){dict = new System.Collections.Generic.Dictionary<string, string>();foreach (SerializationEntry entry in info)dict.Add(entry.Name, (string)entry.Value);}public void GetObjectData(SerializationInfo info, StreamingContext context){foreach (string key in dict.Keys)info.AddValue(key, dict[key]);}}

调用:

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

很抱歉混合了C#和VB.NET…

Json.NET这样做…

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

更多示例:使用Json.NET序列化集合

我确实发现了。NET有一种内置的方式,可以通过3.5System.Web.Extensions程序集中的System.Web.Script.Serialization.JavaScriptSerializer类型将JSON字符串转换为Dictionary<String, Object>。使用方法DeserializeObject(String)

我在对静态. net页面方法进行内容类型为“应用程序/json”的ajax帖子(通过jQuery)时偶然发现了这一点,并看到该方法(具有Object类型的单个参数)神奇地收到了这个字典。

对于那些在互联网上搜索并偶然发现这篇文章的人,我写了一篇关于如何使用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<dynamic>(json);Console.WriteLine(table["id"]);Console.WriteLine(table["value"]);

我也遇到了同样的问题,所以我自己写了这个。这个解决方案与其他答案不同,因为它可以反序列化到多个级别。

只需将JSON字符串发送到de序列化到字典函数,它将返回非强类型的Dictionary<string, object>对象。

旧代码

private Dictionary<string, object> deserializeToDictionary(string jo){var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);var values2 = new Dictionary<string, object>();foreach (KeyValuePair<string, object> 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;}

例如:这将返回Facebook JSON响应的Dictionary<string, object>对象。

测试

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<string, object> values = deserializeToDictionary(responsestring);}

注:家乡进一步沙化成Dictionary<string, object>对象。

更新

如果JSON字符串上没有数组,我的旧答案效果很好。如果元素是数组,则进一步反序列化为List<object>

只需将JSON字符串发送到de序列化到字典或列表函数,它将返回非强类型的Dictionary<string, object>对象或List<object>

private static object deserializeToDictionaryOrList(string jo,bool isArray=false){if (!isArray){isArray = jo.Substring(0, 1) == "[";}if (!isArray){var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);var values2 = new Dictionary<string, object>();foreach (KeyValuePair<string, object> 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<List<object>>(jo);var values2 = new List<object>();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;}}

尝试不使用任何外部JSON实现,所以我像这样反序列化:

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

令人烦恼的是,如果你想使用默认的模型绑定器,看起来你必须使用数字索引值,就像POST表格一样。

请参阅本文http://msdn.microsoft.com/en-us/magazine/hh781022.aspx的以下摘录:

虽然有点违反直觉,但JSON请求具有相同的需求-它们也必须遵守表单后命名语法。以之前UnitPrice的JSON有效负载为例收藏。此数据的纯JSON数组语法将是表示为:

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

但是,默认值提供者和模型绑定器需要要表示为JSON表单的数据帖子:

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

复杂的对象收集场景可能是最复杂的场景之一开发人员遇到的广泛问题场景,因为语法不一定对所有开发人员都很明显。但是,一旦您学习发布复杂集合的相对简单的语法,这些场景变得更容易处理。

如果你想要一种轻量级的、无添加引用的方法,也许我刚刚写的这段代码可以工作(虽然我不能100%保证健壮性)。

using System;using System.Collections.Generic;using System.Text;using System.Text.RegularExpressions;
public Dictionary<string, object> ParseJSON(string json){int end;return ParseJSON(json, 0, out end);}private Dictionary<string, object> ParseJSON(string json, int start, out int end){Dictionary<string, object> dict = new Dictionary<string, object>();bool escbegin = false;bool escend = false;bool inquotes = false;string key = null;int cend;StringBuilder sb = new StringBuilder();Dictionary<string, object> child = null;List<object> 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<object>();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限制#1,但从技术上讲,你没有写,我写了]

我刚刚在RESTSharp中实现了这个。这篇文章对我很有帮助。

除了链接中的代码之外,这是我的代码。当我做这样的事情时,我现在得到了Dictionary的结果:

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

请注意您期望的JSON类型-在我的例子中,我正在检索具有多个属性的单个对象。在附加的链接中,作者正在检索一个列表。

我建议使用System.Runtime.Serialization.Json,它是. NET 4.5的一部分。

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

然后像这样使用它:

var serializer = new DataContractJsonSerializer(typeof(List<Foo>));var jsonParams = @"{""data"": [{""Key"":""foo"",""Value"":""bar""}] }";var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonParams));
var obj = serializer.ReadObject(stream);Console.WriteLine(obj);

我在另一个答案中添加了对JSON中空值的检查

我也遇到了同样的问题,所以我自己写了这个。这个解决方案是区别于其他答案,因为它可以反序列化为多层次

只需将json字符串发送到de序列化到字典函数即可将返回非强类型的Dictionary<string, object>对象。

private Dictionary<string, object> deserializeToDictionary(string jo){var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);var values2 = new Dictionary<string, object>();foreach (KeyValuePair<string, object> 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;}

Ex:这将返回Facebook的Dictionary<string, object>对象JSON响应。

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

注意:家乡进一步反序列化为Dictionary<string, object>对象。

我的方法直接反序列化为IDicpedia,中间没有JObject或ExpanandObject。代码使用转换器,它基本上是从源代码中找到的ExpandoObjectConver类复制JSON.NET,但使用IDicpedia而不是ExpandoObject。

用法:

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

代码:

// based on ExpandoObjectConverter, but using arrays instead of IList, to behave similar to System.Web.Script.Serialization.JavaScriptSerializerpublic 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<string, object>));}
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<string, object>.");}
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<string, object>: {0}", reader.TokenType));}}
private object ReadList(JsonReader reader){List<object> list = new List<object>();
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<string, object>.");}
private object ReadObject(JsonReader reader){IDictionary<string, object> dictionary = new Dictionary<string, object>();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<string, object>.");
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<string, object>.");}
//based on internal Newtonsoft.Json.JsonReader.IsPrimitiveTokeninternal 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.Createprivate 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.Createprivate 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.FormatMessageinternal 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;}}

我在本文中添加了jSnake04和Dasun提交的代码。我添加了从JArray实例创建对象列表的代码。它具有双向递归,但由于它在固定的有限树模型上运行,除非数据庞大,否则没有堆栈溢出的风险。

/// <summary>/// Deserialize the given JSON string data (<paramref name="data"/>) into a///   dictionary./// </summary>/// <param name="data">JSON string.</param>/// <returns>Deserialized dictionary.</returns>private IDictionary<string, object> DeserializeData(string data){var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
return DeserializeData(values);}
/// <summary>/// Deserialize the given JSON object (<paramref name="data"/>) into a dictionary./// </summary>/// <param name="data">JSON object.</param>/// <returns>Deserialized dictionary.</returns>private IDictionary<string, object> DeserializeData(JObject data){var dict = data.ToObject<Dictionary<String, Object>>();
return DeserializeData(dict);}
/// <summary>/// Deserialize any elements of the given data dictionary (<paramref name="data"/>)///   that are JSON object or JSON arrays into dictionaries or lists respectively./// </summary>/// <param name="data">Data dictionary.</param>/// <returns>Deserialized dictionary.</returns>private IDictionary<string, object> DeserializeData(IDictionary<string, object> 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;}
/// <summary>/// Deserialize the given JSON array (<paramref name="data"/>) into a list./// </summary>/// <param name="data">Data dictionary.</param>/// <returns>Deserialized list.</returns>private IList<Object> DeserializeData(JArray data){var list = data.ToObject<List<Object>>();
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;}

Mark Rendle发布了这个作为评论,我想把它作为一个答案发布,因为它是迄今为止唯一有效的解决方案,可以从Google reCaptcha响应中返回成功和错误码json结果。

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

再次感谢,马克!

似乎所有这些答案都只是假设你可以从一个更大的对象中得到那个小字符串……对于那些希望简单地在映射中某处使用这样的字典来实现一个大对象的人,以及使用System.Runtime.Serialization.Json Data合同系统的人,这里有一个解决方案:

回答gis.stackexchange.com这个有趣的链接。我必须用archive.org恢复它,但它提供了一个非常完美的解决方案:一个自定义的IDataContractSurrogate类,您可以在其中完全实现自己的类型。我能够轻松扩展它。

不过,我在其中做了一些更改。由于原始源代码不再可用,我将在此处发布整个类:

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{/// <summary>/// Allows using Dictionary&lt;String,String&gt; and Dictionary&lt;String,Boolean&gt; 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/// </summary>public class JsonSurrogate : IDataContractSurrogate{/// <summary>/// Deserialize an object with added support for the types defined in this class./// </summary>/// <typeparam name="T">Contract class</typeparam>/// <param name="json">JSON String</param>/// <param name="encoding">Text encoding</param>/// <returns>The deserialized object of type T</returns>public static T Deserialize<T>(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<Type, Type> KnownTypes =new Dictionary<Type, Type>()\{\{typeof(Dictionary<String, String>), typeof(SSDictionary)},{typeof(Dictionary<String, Boolean>), typeof(SBDictionary)}};
#region Implemented surrogate dictionary classes
[Serializable]public class SSDictionary : SurrogateDictionary<String>{public SSDictionary() : base() {}protected SSDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}}[Serializable]public class SBDictionary : SurrogateDictionary<Boolean>{public SBDictionary() : base() {}protected SBDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}}
#endregion
/// <summary>Small interface to easily extract the final value from the object.</summary>public interface JsonSurrogateObject{Object DeserializedObject { get; }}
/// <summary>/// Class for deserializing any simple dictionary types with a string as key./// </summary>/// <typeparam name="T">Any simple type that will be deserialized correctly.</typeparam>[Serializable]public abstract class SurrogateDictionary<T> : ISerializable, JsonSurrogateObject{public Object DeserializedObject { get { return dict; } }private Dictionary<String, T> dict;
public SurrogateDictionary(){dict = new Dictionary<String, T>();}
// deserializeprotected SurrogateDictionary(SerializationInfo info, StreamingContext context){dict = new Dictionary<String, T>();foreach (SerializationEntry entry in info){// This cast will only work for base types, of course.dict.Add(entry.Name, (T)entry.Value);}}// serializepublic void GetObjectData(SerializationInfo info, StreamingContext context){foreach (String key in dict.Keys){info.AddValue(key, dict[key]);}}
}
/// <summary>/// Uses the KnownTypes dictionary to get the surrogate classes./// </summary>/// <param name="type"></param>/// <returns></returns>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();}
/// <summary>///     Gets the object out of the surrogate datacontract object. This function is the reason all surrogate objects need to implement the JsonSurrogateObject class./// </summary>/// <param name="obj">Result of the deserialization</param>/// <param name="targetType">Expected target type of the deserialization</param>/// <returns></returns>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<Type> customDataTypes){throw new NotImplementedException();}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit){throw new NotImplementedException();}
#endregion}}

要向类中添加新的受支持的类型,你只需要添加你的类,给它正确的构造函数和函数(举个例子,看看SurrogateDictionary),确保它继承了JsonSurrogateObject,并将其类型映射添加到KnownTypes字典。包含的Surro ateDicpedia可以作为任何Dictionary<String,T>类型的基础,其中T是任何正确反序列化的类型。

调用它非常简单:

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

请注意,由于某种原因,这个东西在使用包含空格的键字符串时遇到了麻烦;它们根本不存在于最终列表中。可能只是针对json规范,我调用的api实现得很差,请注意;我不知道。无论如何,我通过在原始json数据中用下划线替换它们并在反序列化后修复字典来解决这个问题。

我只需要解析一个嵌套字典,就像

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

其中JsonConvert.DeserializeObject没有帮助。我找到了以下方法:

var dict = JObject.Parse(json).SelectToken("x").ToObject<Dictionary<string, int>>();

SelectToken允许您向下挖掘所需的字段。您甚至可以指定像"x.y.z"这样的路径来进一步深入JSON对象。

你可以使用Tiny-JSON

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

这个游戏有点晚了,但是上面的解决方案都没有给我指出一个纯粹而简单的方向。NET,没有json.net的解决方案。所以在这里,最终变得非常简单。下面是一个完整的运行示例,说明如何使用标准. NET Json序列化,该示例在根对象和子对象中都有字典。

黄金子弹是这只猫,解析设置作为序列化器的第二个参数:

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<string,Child> Children { get; set; }}
[DataContract]public class Child{[DataMember(Name = "name")]public string Name { get; set; }
[DataMember(Name = "subs")]public Dictionary<int, Sub> 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);}}}}}}

基于评论上面尝试JsonConvert.DeserializeObject<Dictionary<string,dynamic>>(json)

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

似乎甚至适用于复杂的对象和列表。

System. Text. Json

现在可以使用. NET Core 3.0内置的System.Text.Json来完成。现在可以使用第三方库反序列化JSON没有

var json = @"{""key1"":""value1"",""key2"":""value2""}";var values = JsonSerializer.Deserialize<Dictionary<string, string>>(json);

如果使用. NET Standard或. NET Framework,也可在NuGet包系统文本信息中使用。


请务必阅读并理解:

对于任何试图将JSON转换为字典只是为了从中检索一些值的人。有一个简单的方法使用Newtonsoft.JSON

using Newtonsoft.Json.Linq...
JObject o = JObject.Parse(@"{'CPU': 'Intel','Drives': ['DVD read/writer','500 gigabyte hard drive']}");
string cpu = (string)o["CPU"];// Intel
string firstDrive = (string)o["Drives"][0];// DVD read/writer
IList<string> allDrives = o["Drives"].Select(t => (string)t).ToList();// DVD read/writer// 500 gigabyte hard drive

这是我使用System. Text. Json的解决方案。您将获得嵌套对象的json字符串,稍后可以将其转换为所需的类型。

public static Dictionary<string,string> JsonToDictionary(this string json){var objectValues = JsonSerializer.Deserialize<Dictionary<string, object>>(json);var stringValues = objectValues.Select(o => new KeyValuePair<string, string>(o.Key, o.Value?.ToString()));return stringValues.ToDictionary(pair => pair.Key, pair => pair.Value);}

以下是从嵌套对象中获取值的用法示例:

 var result= json.JsonToDictionary()["outerField"].JsonToDictionary()["innerField"];

请注意,此解决方案不包括以数组开头的json对象,如[12,13]。这些对象可以在开始时作为数组读取,然后可以对每个项目应用扩展方法,以防这些项目是具有自己属性的复杂对象。