首先謝謝大家的支持和關注.本章主要介紹.Net類型與JSON是如何映射的.我們知道JSON中類型基本上有三種:值類型,數組和對象.而.Net中的類型比較多.到底它們是如何映射的呢?
總體來講,Json.Net將.Net中的基本類型(int,float,string等)轉換為Json的值,數組和集合轉換為Json的數組,其它轉換為Json對象.
如果你自定義了實現了數組和集合的類,並為類添加了自己的屬性,抱歉在序列化時,該屬性不會被序列化.例如我定義了如下的集合:
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是僅僅序列化公有成員的.多出來的值是繼承的接口中的屬性.
字典類型(Dictionary,IDictionary,Hashtable等)會被序列化為對象,是以其中的key/value的形式來序列化,額外添加的屬性不會被序列化.這里不再詳講了.
在.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!有什么問題,請及時告訴我啊!一起學習!