将JSON对象层次结构反序列化为Dictionary 的层次结构

我在.NET中用于WinRT(C#) ,我想将JSON字符串反序列化为Dictionary ,其中字典值稍后可以转换为实际类型。 JSON字符串可以包含对象层次结构,我想在Dictionary中也有子对象。

这是一个它应该能够处理的示例JSON:

 { "Name":"John Smith", "Age":42, "Parent": { "Name":"Brian Smith", "Age":65, "Parent": { "Name":"James Smith", "Age":87, } } } 

我尝试使用DataContractJsonSerializer这样做:

 using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) { DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings(); settings.UseSimpleDictionaryFormat = true; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary), settings); Dictionary results = (Dictionary)serializer.ReadObject(ms); } 

这实际上适用于第一级,但是“Parent”只是一个无法转换为Dictionary

 Dictionary parent = (Dictionary)results["Parent"]; Cannot cast 'results["Parent"]' (which has an actual type of 'object') to 'System.Collections.Generic.Dictionary' 

然后我尝试使用Json.NET,但子对象是JObject本身是IDictionary ,这迫使我迭代完整的层次结构并将它们重新转换。

有人知道如何使用现有的序列化器来解决这个问题吗?

编辑

我正在使用Dictionary因为我的对象从一个服务器调用到另一个服务器调用(例如“Id”属性可能是“id” ,*“cust_id”*或“customerId”,具体取决于请求)和我的应用程序不是唯一使用这些服务的应用程序,我无法改变它,至少目前是这样。

因此,我发现在这种情况下使用DataContractAttributeDataMemberAttribute很不方便。 相反,我想将所有内容存储在通用字典中,并且只有一个强类型属性“Id”,它在字典中查找“id”,“cust_id”或“customerId”,使其对UI透明。

这个系统适用于JSON.NET,但是如果服务器返回一个对象层次结构,子对象将作为JObjects存储在我的字典而不是另一个字典中。

总而言之,我正在寻找一种有效的系统Dictionary使用WinRT中提供的JSON序列化器将对象层次结构转换为Dictionary的层次结构。

我正在使用JSON.NET库和ExpandoObject类的组合在WinRT应用程序中解决同样的问题。 该库能够很好地将JSON数据反序列化为实现IDictionary的ExpandoObjects。 ExpandoObject的键值对的值可以很容易地被视为另一个ExpandoObject。

这是我使用的方法,适用于您的样本:

 void LoadJSONData() { string testData = "{ \"Name\":\"John Smith\", \"Age\":42, \"Parent\": { \"Name\":\"Brian Smith\", \"Age\":65, \"Parent\": { \"Name\":\"James Smith\", \"Age\":87, } } }"; ExpandoObject dataObj = JsonConvert.DeserializeObject(testData, new ExpandoObjectConverter()); // Grab the parent object directly (if it exists) and treat as ExpandoObject var parentElement = dataObj.Where(el => el.Key == "Parent").FirstOrDefault(); if (parentElement.Value != null && parentElement.Value is ExpandoObject) { ExpandoObject parentObj = (ExpandoObject)parentElement.Value; // do something with the parent object... } // Alternately, iterate through the properties of the expando foreach (var property in (IDictionary)dataObj) { if (property.Key == "Parent" && property.Value != null && property.Value is ExpandoObject) { foreach (var parentProp in (ExpandoObject)property.Value) { // do something with the properties in the parent expando } } } } 

试试这段代码片段:

 var d = new System.Web.Script.Serialization.JavaScriptSerializer(); var results = d.Deserialize>(jsonString); var parent = (Dictionary)results["Parent"]; 

根据参考资料, JavaScriptSerializer Class支持Windows 8

对于反序列化, Json.NET也是一个可以考虑Windows 8支持的选项。

添加 ,对于WinRT

  1. 根据您的JSON定义DataContract

     [DataContract] public class CustomObject { [DataMember(Name = "Name")] public string Name { get; set; } [DataMember(Name = "Age")] public string Age { get; set; } [DataMember(Name = "Parent")] public Dictionary Parent { get; set; } } 
  2. 反序列化时使用DataContract类。

     using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) { DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings(); settings.UseSimpleDictionaryFormat = true; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CustomObject), settings); CustomObject results = (CustomObject)serializer.ReadObject(ms); Dictionary parent = results.Parent; } 

参考: 使用DataContractJsonSerializer从JSON创建.NET对象