C#におけるDynamicとJson文字列の相互変換

4412 ワード

呼び出し:
ynamic d = new ExpandoObject();
d.Name = "Tom";
string json = JsonDynamic.ToJson(d);//{"Name":"Tom"}
dynamic d2 = JsonDynamic.ToDynamic(json);

注意:Jsonにシーケンス化すると、ExpandoOjbectタイプのみがサポートされます.ExpandoOjbectはIDictionaryから派生し、属性値を取得できます.一方、DynamicObjectから派生したタイプオブジェクトは、IDictionaryインタフェースを実装することでシーケンス化を容易にすることもできます.逆シーケンス化されたダイナミックオブジェクトは、DynamicObjectからカスタム拡張されたDynamicJsonObjectタイプです.
コード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Web.Script.Serialization;
using System.Collections;

namespace Jingven.Utility
{
    public class JsonDynamic
    {
        public static dynamic ToDynamic(string json)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
            dynamic dy = jss.Deserialize(json, typeof(object)) as dynamic;
            return dy;  
        }
        public static string ToJson(dynamic d)
        {
            JavaScriptSerializer oSerializer = new JavaScriptSerializer();
            oSerializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJSONConverter() });
            string json = oSerializer.Serialize(d);
            return json;
        }
    }
    public class DynamicJsonConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null)
                throw new ArgumentNullException("dictionary");

            if (type == typeof(object))
            {
                return new DynamicJsonObject(dictionary);
            }

            return null;
        }

        public override IDictionary Serialize(object obj, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override IEnumerable SupportedTypes
        {
            get { return new ReadOnlyCollection(new List(new Type[] { typeof(object) })); }
        }
    }
    public class DynamicJsonObject : DynamicObject
    {
        private IDictionary Dictionary { get; set; }

        public DynamicJsonObject(IDictionary dictionary)
        {
            this.Dictionary = dictionary;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = this.Dictionary[binder.Name];

            if (result is IDictionary)
            {
                result = new DynamicJsonObject(result as IDictionary);
            }
            else if (result is ArrayList && (result as ArrayList) is IDictionary)
            {
                result = new List((result as ArrayList).ToArray().Select(x => new DynamicJsonObject(x as IDictionary)));
            }
            else if (result is ArrayList)
            {
                result = new List((result as ArrayList).ToArray());
            }

            return this.Dictionary.ContainsKey(binder.Name);
        }
    }
    public class ExpandoJSONConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override IDictionary Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary();
            var dictionary = obj as IDictionary;

            foreach (var item in dictionary)
                result.Add(item.Key, item.Value);

            return result;
        }

        public override IEnumerable SupportedTypes
        {
            get
            {
                return new ReadOnlyCollection(new Type[] { typeof(System.Dynamic.ExpandoObject) });
            }
        }
    }
}