繁体   English   中英

将JSON对象层次结构反序列化为Dictionary <string,object>的层次结构

[英]Deserializing a JSON object hierarchy into a hierarchy of Dictionary<string, object>

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

这是一个它应该能够处理的示例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<string, object>), settings);
    Dictionary<string, object> results = (Dictionary<string, object>)serializer.ReadObject(ms);
}

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

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

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

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

编辑

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

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

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

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

我正在使用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<ExpandoObject>(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<String, Object>)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<Dictionary<string, object>>(jsonString);
var parent = (Dictionary<string, object>)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<string, object> 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<string, object> parent = results.Parent; } 

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM