[英]JavaScriptConverter, ExpandoObject and dynamic types
我有一个像这样的小测试班:
public class Command
{
public dynamic MyData { get; set; }
}
作为dynamic MyData
我想使用ExpandoObject,所以我可以这样做:
Command cmd = new Command();
cmd.MyData = new ExpandoObject();
cmd.MyData.SomeStuff = 4;
cmd.MyData.SomeOtherStuff = "hi";
我正在尝试从json序列化/反序列化。 为此,我正在使用JavaScriptSerializer
。
我想要上面的示例对象序列化为:
{
MyData : {
SomeStuff : 4,
SomeOtherStuff : "hi"
}
}
为此,我需要一个JavaScriptConverter
(从此网站获取 ):
public class ExpandoJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
return dictionary.ToExpando();
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var result = new Dictionary<string, object>();
var dictionary = obj as IDictionary<string, object>;
foreach (var item in dictionary)
result.Add(item.Key, item.Value);
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get
{
return new ReadOnlyCollection<Type>(new Type[] { typeof(ExpandoObject) });
}
}
}
public static class IDictionaryExtensions {
/// <summary>
/// Extension method that turns a dictionary of string and object to an ExpandoObject
/// Snagged from http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
/// </summary>
public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary) {
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;
// go through the items in the dictionary and copy over the key value pairs)
foreach (var kvp in dictionary) {
// if the value can also be turned into an ExpandoObject, then do it!
if (kvp.Value is IDictionary<string, object>) {
var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key, expandoValue);
}
else if (kvp.Value is ICollection) {
// iterate through the collection and convert any strin-object dictionaries
// along the way into expando objects
var itemList = new List<object>();
foreach (var item in (ICollection)kvp.Value) {
if (item is IDictionary<string, object>) {
var expandoItem = ((IDictionary<string, object>)item).ToExpando();
itemList.Add(expandoItem);
}
else {
itemList.Add(item);
}
}
expandoDic.Add(kvp.Key, itemList);
}
else {
expandoDic.Add(kvp);
}
}
return expando;
}
}
现在,它可以很好地进行序列化 ,但是反 序列化存在以下问题:
MyData
是dynamic
对象,并且ExpandoJsonConverter
需要ExpandoObject,因此反序列化为MyData
的数据的类型为IDictionary<string, object>
。 dynamic MyData
更改为ExpandoObject MyData
,则无法说cmd.MyData.SomeStuff = 4;
,编译器会告诉我“ ExpandoObject没有名为SomeStuff的属性”。 dynamic
添加到ExpandoJsonConverter
支持的类型列表中,再等等,您不能执行typeof(dynamic)
。 有谁知道一个整洁的解决方法? 我真的很喜欢这个功能,但是我不能使用Newtonsoft之类的第三方序列化库。 谢谢。
反序列ExpandoObject
但声明变量dynamic
,即您需要的是dynamic d = js.Deserialize<ExpandoObject>(json)
:
string json = @"{
MyData : {
SomeStuff : 4,
SomeOtherStuff : ""hi""
}
}";
var js = new JavaScriptSerializer();
js.RegisterConverters(new[] { new ExpandoJsonConverter() });
dynamic d = js.Deserialize<ExpandoObject>(json);
Console.WriteLine(d.MyData.SomeOtherStuff);
输出:
你好
如果需要Command
对象,只需手动构造一个对象,然后注入从序列化器返回的dynamic
对象:
var cmd = new Command { MyData = d };
Console.WriteLine(cmd.MyData.SomeStuff);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.