事情從Json的序列化和反序列化提及。html
在C#2.0的項目中,之前常常使用Json.Net實現序列化和反序列化。後來從c#3.0中開始使用新增的DataContractJsonSerializer進行json相關的操做。微軟提供的原生類庫使用上並不複雜,參考一下msdn你很容易就會寫出序列化和反序列化的方法,好比常常被人使用的泛型方法以下:json
public class JsonHelper { /// <summary> /// 對象轉換成json /// </summary> /// <typeparam name="T"></typeparam> /// <param name="jsonObject">須要格式化的對象</param> /// <returns>Json字符串</returns> public static string DataContractJsonSerialize<T>(T jsonObject) { var serializer = new DataContractJsonSerializer(typeof(T)); string json = null; using (var ms = new MemoryStream()) //定義一個stream用來存發序列化以後的內容 { serializer.WriteObject(ms, jsonObject); var dataBytes = new byte[ms.Length]; ms.Position = 0; ms.Read(dataBytes, 0, (int)ms.Length); json = Encoding.UTF8.GetString(dataBytes); ms.Close(); } return json; } /// <summary> /// json字符串轉換成對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="json">要轉換成對象的json字符串</param> /// <returns></returns> public static T DataContractJsonDeserialize<T>(string json) { var serializer = new DataContractJsonSerializer(typeof(T)); var obj = default(T); using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) { obj = (T)serializer.ReadObject(ms); ms.Close(); } return obj; } }不過使用該類庫方法的過程當中仍是不慎意外發現了k_BackingField。
舉例以前說一下咱們的一個簡單的實體類Person,它有以下定義:c#
public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime Birthday { get; set; } }
若是Person沒有附加任何特性,經測試,能夠成功使用上述泛型方法進行處理。post
var person = new Person { Id = 1, FirstName = "jeff", LastName = "wong", Birthday = new DateTime(1983, 8, 3) }; var json = JsonHelper.DataContractJsonSerialize<Person>(person); Console.WriteLine(json); var result = JsonHelper.DataContractJsonDeserialize<Person>(json); if (result != null) { Console.WriteLine("{0} {1}", result.FirstName, result.LastName); }
並且json生成是正常的字符串:測試
{"Birthday":"\/Date(428688000000+0800)\/","FirstName":"jeff","Id":1,"LastName":"wong"}
但是當咱們把Person實體上面設置Serializable特性後,莫名,我就很不解了:spa
{"<Birthday>k__BackingField":"\/Date(428688000000+0800)\/","<FirstName>k__BackingField":"jeff","<Id>k__BackingField":1,"<LastName>k__BackingField":"wong"}
搜索了一下,果真早就有人發現了相似的問題。後來上stackoverflow一查,查到好像和自動屬性有點關係,你們能夠看一下這一篇和這一篇,並且評論比原帖精彩好像國內外大部分都是一致的。.net
有人說用Reflector反彙編能夠看到自動屬性生成的字段有前綴,惋惜我一直使用ILSpy,興致勃勃反編譯查看了一下,沒有沒有是真的沒有啊。code
到這裏你可能會想到,自動屬性json會有k_BackingField前綴,那傳統那種屬性的寫法呢?orm
[Serializable] public class Person { private int id; public int Id { get { return id; } set { id = value; } } private string firstName; public string FirstName { get { return firstName; } set { firstName = value; } } private string lastName; public string LastName { get { return lastName; } set { lastName = value; } } private DateTime birthday; public DateTime Birthday { get { return birthday; } set { birthday = value; } } }
OK,咱們想一塊去了,經測試,帶Serializable特性的Person類,輸出json一點問題沒有:htm
{"birthday":"\/Date(428688000000+0800)\/","firstName":"jeff","id":1,"lastName":"wong"}
可是,請注意大小寫(我挖了一個坑,上面的json是序列化屬性嗎?首字母有沒有大寫?)。
有沒有兼容方式使自動屬性輸出json也正常呢?很簡單,使用DataContract和DataMember屬性,哪種寫法輸出json都沒有問題的:
json輸出帶有k_BackingField前綴的問題可能很是簡單,這裏只是善意地提醒,我我的曾經有過「慘痛」的教訓,並且感受還至關隱蔽,你們也要當心啊。
最後,在使用.net framework自帶的json有關類庫的時候還碰到過特殊符號和時間格式轉換的問題,網上有很多文章都講到,相信很多人也有相似經歷,這裏就不說了。
參考:
http://geekswithblogs.net/sdorman/archive/2007/08/08/C-3.0-Automatic-Properties.aspx
http://stackoverflow.com/questions/945585/c-sharp-automatic-property-deserialization-of-json
http://www.cnblogs.com/goldarch/archive/2011/04/25/2027071.html
http://computeroverlord.tumblr.com/post/34781472/deserialization-problems-k-backingfield
轉自:http://www.cnblogs.com/jeffwongishandsome/archive/2012/05/31/2529196.html