[英]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”取決於請求)和我的應用程序不是唯一使用這些服務的應用程序,我無法改變它,至少目前是這樣。
因此,我發現在這種情況下使用DataContractAttribute和DataMemberAttribute很不方便。 相反,我想將所有內容存儲在通用字典中,並且只有一個強類型屬性“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
:
根據您的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; } }
反序列化時使用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; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.