Json.Net系列教程 2.Net類型與JSON的映射關系


首先謝謝大家的支持和關注.本章主要介紹.Net類型與JSON是如何映射的.我們知道JSON中類型基本上有三種:值類型,數組和對象.而.Net中的類型比較多.到底它們是如何映射的呢?

總體來講,Json.Net將.Net中的基本類型(int,float,string等)轉換為Json的值,數組和集合轉換為Json的數組,其它轉換為Json對象.

1.基本類型:

2.復雜類型:

3.注意
3.1數組和集合

如果你自定義了實現了數組和集合的類,並為類添加了自己的屬性,抱歉在序列化時,該屬性不會被序列化.例如我定義了如下的集合:

    public class MyArray : ArrayList
    {
        public string Name { get; set; }
    }

實例化該類並序列化

            MyArray ma = new MyArray { Name = "myArray" };
            ma.Add(1);
            ma.Add(2);
            ma.Add(3);
            string json = JsonConvert.SerializeObject(ma);
            Console.WriteLine(json);

效果:

如果我想把數組以對象的形式序列化,可不可以呢?答案是肯定的!
只要在定義的數組類的前面加上特性"JsonObject"即可,當然先要引入命名空間"Newtonsoft.Json".

    [JsonObject]
    public class MyArray : ArrayList
    {
        public string Name { get; set; }
    }

結果:

 是的,你會發現結果中沒有我們添加的值了,並且多出了很多其他我們並沒有定義的值,這是因為我們添加的值在ArrayList中是以私有數組來存儲的,默認情況下,Json.Net是僅僅序列化公有成員的.多出來的值是繼承的接口中的屬性.

3.2字典類型

字典類型(Dictionary,IDictionary,Hashtable等)會被序列化為對象,是以其中的key/value的形式來序列化,額外添加的屬性不會被序列化.這里不再詳講了.

3.3Dynamic類型

在.Net4.0中,Dynamic基本上有兩種用法.
一種是作為屬性來用,在這種情況下序列化時會根據實際的類型來序列化.
第二種用法是繼承了IDynamicMetaObjectProvider 接口或者DynamicObject 基類,例如.Net中內置的類ExpandoObject ,這三者之間的關系是:ExpandoObject,DynamicObject都繼承了IDynamicMetaObjectProvider.這種情況下,只有DynamicMetaObject.GetDynamicMemberNames的返回的成員的屬性會被序列化.

 首先新建一個類,繼承基類 DynamicObject

    public class MyDynamic : DynamicObject
    {
        //用來存儲動態添加的變量和值
        private Dictionary<string, object> members = new Dictionary<string, object>();

        /// <summary>
        /// 獲取所有的動態成員名稱
        /// </summary>
        /// <returns>動態成員名稱</returns>
        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return members.Keys;
        }

        /// <summary>
        /// 設置動態成員名稱,也就是在發生賦值語句時出發該方法
        /// 例如:dynamic dy = new MyDynamic();
        /// dy.Name = "Jack";
        /// </summary>
        /// <param name="binder">用於動態設置操作</param>
        /// <param name="value">預設的值</param>
        /// <returns></returns>
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (!members.ContainsKey(binder.Name))
            {
                members.Add(binder.Name, value);
            }
            else
                members[binder.Name] = value;
            return true;
        }

        /// <summary>
        /// 根據名稱獲取動態成員的值
        ///  例如:dynamic dy = new MyDynamic();
        ///  var name = dy.Name;
        /// </summary>
        /// <param name="binder">用戶動態獲取操作</param>
        /// <param name="result">將獲取的值賦給的對象</param>
        /// <returns></returns>
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (members.ContainsKey(binder.Name))
            {
                result = members[binder.Name];
                return true;
            }
            else
                return base.TryGetMember(binder, out result);
        }

        /// <summary>
        /// 如果成員的類型是委托,則調用它
        /// </summary>
        /// <param name="binder">用戶動態委托操作</param>
        /// <param name="args">委托調用的參數</param>
        /// <param name="result">委托調用返回的結果</param>
        /// <returns></returns>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            if (members.ContainsKey(binder.Name) && members[binder.Name] is Delegate)
            {
                result = (members[binder.Name] as Delegate).DynamicInvoke(args);
                return true;
            }
            else
            {
                return base.TryInvokeMember(binder, args, out result);
            }
        }
    }

在主程序中,做如下操作:

            dynamic md = new MyDynamic();//必須是用dynamic來聲明變量,不能用MyDynamic,否則它就不是動態類型了。
              md.Name = "Jack";
            Action<string> output = new Action<string>((value) => { Console.WriteLine(value); });
            md.Output = output;
            Console.WriteLine(JsonConvert.SerializeObject(md));
            md.Output(md.Name);

結果:

是的,委托類型也被序列化了,這並不是我們想要的,有沒有方法來將它排除呢?答案就在GetDynamicMemberNames方法,默認我們返回的是所有的Keys,只要我們加一定的限制條件即可.修改之后的代碼

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            foreach (string key in members.Keys)
            {
                if(!(members[key] is Delegate))
                    yield return key;
            }
        }

此時的運行結果:

 OK!有什么問題,請及時告訴我啊!一起學習!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM