事情从Json的序列化和反序列化说起。

在C#2.0的项目中,以前经常使用Json.Net实现序列化和反序列化。后来从c#3.0中开始使用新增的DataContractJsonSerializer进行json相关的操作。微软提供的原生类库使用上并不复杂,参考一下msdn你很容易就会写出序列化和反序列化的方法,比如经常被人使用的泛型方法如下:

/// <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,它有如下定义:

public class Person
    {
        public int Id { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public DateTime Birthday { get; set; }
    }

如果Person没有附加任何特性,经测试,可以成功使用上述泛型方法进行处理。

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特性后,莫名,我就很不解了:

{"<Birthday>k__BackingField":"\/Date(428688000000+0800)\/","<FirstName>k__BackingField":"jeff","<Id>k__BackingField":1,"<LastName>k__BackingField":"wong"}

搜索了一下,果然早就有人发现了类似的问题。后来上stackoverflow一查,查到好像和自动属性有点关系,大家可以看一下这一篇和这一篇,而且评论比原帖精彩好像国内外大部分都是一致的。

有人说用Reflector反汇编可以看到自动属性生成的字段有前缀,可惜我一直使用ILSpy,兴致勃勃反编译查看了一下,没有没有是真的没有啊。

到这里你可能会想到,自动属性json会有k_BackingField前缀,那传统那种属性的写法呢?

[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一点问题没有:

{"birthday":"\/Date(428688000000+0800)\/","firstName":"jeff","id":1,"lastName":"wong"}

但是,请注意大小写(我挖了一个坑,上面的json是序列化属性吗?首字母有没有大写?)。

有没有兼容方式使自动属性输出json也正常呢?很简单,使用DataContract和DataMember属性,哪一种写法输出json都没有问题的:

[DataContract]
    public class Person
    {
        [DataMember]
        public int Id { get; set; }

[DataMember]
        public string FirstName { get; set; }

[DataMember]
        public string LastName { get; set; }

[DataMember]
        public DateTime Birthday { get; set; }
    }

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://stackoverflow.com/questions/340528/c-sharp-automatic-properties-why-do-i-have-to-write-get-set

http://www.cnblogs.com/goldarch/archive/2011/04/25/2027071.html

http://computeroverlord.tumblr.com/post/34781472/deserialization-problems-k-backingfield

认识k_BackingField,微软自己的序列化和反序列化的更多相关文章

  1. C#对 Json的序列化和反序列化时出现“k_BackingField”

    在C#2.0的项目中,以前经常使用Json.NET实现序列化和反序列化.后来从c#3.0中开始使用新增的DataContractJsonSerializer进行json相关的操作.微软提供的原生类库使 ...

  2. Json的序列化与反序列化以及乱入的k_BackingField

    0.Newtonsoft.json 最简单的最强大的基于c#的json解析库是Newtonsoft.json 在NuGet程序包管理器中在线搜索“json”,选择JSon.Net,并安装.   使用到 ...

  3. C# 序列化与反序列化

    我们先说说什么是序列化.所谓的序列化就是把要保存的内容以特定的格式存入某种介质中.比如我们要保存一些数据在下次程序启动的时候再读入.我们一般就是把这个数据写在一个本地的文本中.然后程序启动的时候去读入 ...

  4. Net中JSON序列化和反序列化处理(日期时间特殊处理)

    0  缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...

  5. C# JSON字符串序列化与反序列化

    JSON与c#对象转换http://hi.baidu.com/donick/item/4d741338870c91fe97f88d33 C# JSON字符串序列化与反序列化 – http://www. ...

  6. 在net中json序列化与反序列化

    准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...

  7. Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串

    原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...

  8. 给Ajax一个漂亮的嫁衣——Ajax系列之五(下)之序列化和反序列化

    给Ajax一个漂亮的嫁衣——Ajax系列之五(下)之序列化和反序列化 标签: ajaxdictionaryjsonobject服务器function 2012-07-25 18:41 2242人阅读  ...

  9. LintCode-7-二叉树的序列化和反序列化

    二叉树的序列化和反序列化 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为"序列化",读取文件后重建同样的二叉树被称为"反序列化". 如 ...

随机推荐

  1. Java高并发syncronized深入理解

    1.Synchronized的作用: 能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果. 2.地位: 1)Synchronized是java的关键字,并java的怨言原生支持: ...

  2. 算法笔记_197:历届试题 带分数(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. ...

  3. SQL入门教程

    SQL SELECT DISTINCT 语句 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值. 语法 ...

  4. ORA-14300: 分区关键字映射到超出允许的最大分区数的分区

    环境为:Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production 对象表为按天的自动分区表: PARTI ...

  5. 通过导入虚拟电脑的方式还原centos

    通过oracle vm VirtualBox安装完成一台centos,然后导出虚拟电脑,再通过导入虚拟电脑的方式还原一台centos,还原的时候改一下机器名,不要选择重新初始化所有网卡mac,还原完成 ...

  6. python之函数用法staticmethod

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法staticmethod #http://www.cnblogs.com/hongfe ...

  7. Java 爬虫(获取指定页面中所有的邮箱地址)

    import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.io.In ...

  8. LRM-00109-ORACLE启动报错

    不经意间的错误操作,万里堤坝溃于蚁穴! 问题描述: SQL> startupORA-01078: failure in processing system parametersLRM-00109 ...

  9. bzoj1296【SCOI2009】粉刷匠

    1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1479  Solved: 837 [id=1296" ...

  10. TCP Socket 粘包

     这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题.发现自己不是非常清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接: 1.长连接 Client方与Server ...