4

我在.NET for WinRT (C#)中,我想将 JSON 字符串反序列化为 a 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);
}

这实际上适用于第一级,但“父”只是一个不能转换为的对象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 配合得很好,但是如果服务器返回一个对象层次结构,子对象将作为 JObjects 存储在我的字典中,而不是另一个字典中。

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

4

2 回答 2

4

我正在使用 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
            }
        }
    }
}
于 2012-11-30T17:12:25.630 回答
3

试试这段代码片段:

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

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

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

添加,对于WinRT

  1. DataContract根据您的 JSON定义。

    [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 对象

于 2012-11-29T17:26:10.827 回答