簡體   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