C# JavaScriptConverter、ExpandoObject和动态类型
我有一个这样的小测试班:C# JavaScriptConverter、ExpandoObject和动态类型,c#,.net,json,javascriptserializer,expandoobject,C#,.net,Json,Javascriptserializer,Expandoobject,我有一个这样的小测试班: public class Command { public dynamic MyData { get; set; } } 由于动态MyData我想使用ExpandoObject,所以我可以: Command cmd = new Command(); cmd.MyData = new ExpandoObject(); cmd.MyData.SomeStuff = 4; cmd.MyData.SomeOtherStuff = "hi"; 我正在尝试从json序列
public class Command
{
public dynamic MyData { get; set; }
}
由于动态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
(取自):
公共类ExpandoJsonConverter:JavaScriptConverter
{
公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序)
{
返回dictionary.ToExpando();
}
公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序)
{
var result=newdictionary();
var dictionary=obj作为IDictionary;
foreach(字典中的变量项)
结果.添加(item.Key,item.Value);
返回结果;
}
公共覆盖IEnumerable SupportedTypes
{
收到
{
返回新的只读集合(新类型[]{typeof(ExpandoObject)});
}
}
}
公共静态类IDictionaryExtensions{
///
///将字符串和对象的字典转换为ExpandooObject的扩展方法
///从http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
///
公共静态ExpandoObject to Expando(此IDictionary字典){
var expando=新的ExpandoObject();
var expandoDic=(IDictionary)expando;
//检查字典中的项目并复制键值对)
foreach(字典中的var kvp){
//如果该值也可以转换为ExpandooObject,那么请执行该操作!
if(kvp.Value是IDictionary){
var expandoValue=((IDictionary)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key,expandoValue);
}
否则如果(kvp.Value为ICollection){
//遍历集合并转换任何strin对象字典
//在进入expando对象的过程中
var itemList=新列表();
foreach(在(ICollection)kvp.Value中的变量项){
if(项为IDictionary){
var expandoItem=((IDictionary)项).ToExpando();
itemList.Add(expandoItem);
}
否则{
项目列表。添加(项目);
}
}
expandoDic.Add(kvp.Key,itemList);
}
否则{
expandoDic.Add(kvp);
}
}
返回expando;
}
}
现在,这对于序列化非常有效,但反序列化存在以下问题:
- 由于
是一个MyData
对象,并且dynamic
需要ExpandoObject,因此反序列化到ExpandoJsonConverter
的数据属于MyData
类型李>IDictionary
- 如果我将
更改为dynamic MyData
,我将不能说ExpandoObject MyData
cmd.MyData.SomeStuff=4代码>,编译器会告诉我“ExpandooObject没有名为SomeStuff的属性”
- 最后,我可以将
添加到支持的dynamic
类型列表中,通过等待,您不能执行ExpandoJsonConverter
typeof(dynamic)
有人知道一个整洁的解决方法吗?我真的很喜欢这个功能,但是我不能使用第三方序列化库,比如Newtonsoft。谢谢。反序列化到
ExpandoObject
,但声明变量dynamic
,即您需要的是dynamic d=js。反序列化(json)
:
能满足您的要求吗?谢谢您的回复。同样,整个主题都是关于序列化为JSON的,我已经实现了这一点。我的问题是相反的(反序列化JSON),它返回字典而不是ExpandoObject。
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;
}
}
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);
var cmd = new Command { MyData = d };
Console.WriteLine(cmd.MyData.SomeStuff);