2012-11-29 42 views
3

我在.NET for WinRT(C#)我想將JSON字符串反序列化爲Dictionary<string, object>,其中字典值可以稍後將轉換爲實際類型。 JSON字符串可以包含一個對象層次結構,我也想在Dictionary<string, object>中有子對象。將JSON對象層次結構反序列化爲字典層次結構<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」,使其對用戶界面透明。

該系統對JSON.NET非常有效,但是如果服務器返回一個對象層次結構,子對象將作爲JObjects存儲在我的字典中而不是另一個字典中。總結一下,我正在尋找一個高效的系統,使用WinRT中提供的JSON序列化程序將對象層次轉換爲層次結構Dictionary<string, object>

+0

看到我的編輯答案。希望這可以幫助! –

回答

3

我使用的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 
      } 
     } 
    } 
} 
+0

非常有趣,它看起來像我在找什麼。今天我會試一試,看看它是否合適(功能和表現力)! – canderso

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 Class支持Windows 8的

對於反序列化,Json.NET也是一個選項,可以考慮用Windows 8支持。

ADDED,對於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; 
    } 
    

參考:Creating .NET objects from JSON using DataContractJsonSerializer

+0

請注意,該類型包含在System.Web.Extensions程序集中。它是否可用於WinRT應用程序? – fsimonazzi

+0

根據我的發現迄今爲止...是的,http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx和http://msdn.microsoft.com/ en-us/library/system.web.script.serialization.javascriptserializer.aspx –

+0

嗯,它不會顯示在支持的API列表中http://msdn.microsoft.com/zh-cn/library/windows/apps /br230232.aspx – fsimonazzi