博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
认识k_BackingField,微软自己的序列化和反序列化
阅读量:7235 次
发布时间:2019-06-29

本文共 3447 字,大约阅读时间需要 11 分钟。

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

{"
k__BackingField":"\/Date(428688000000+0800)\/","
k__BackingField":"jeff","
k__BackingField":1,"
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://yeofm.baihongyu.com/

你可能感兴趣的文章
Android任务队列使用
查看>>
Swift语法对编译速度的影响
查看>>
如何在Python下搭建QT+SIP+PyQt5环境
查看>>
说说在 Linux 中如何查看系统信息
查看>>
iphone 常用的app info plist设置
查看>>
快速排序算法的实现
查看>>
排序面试 java版
查看>>
python-16-元类和异常
查看>>
2017 JavaScript 主流框架性能总结
查看>>
Class详解
查看>>
正则:此处用到字符串的replace方法
查看>>
什么是css?
查看>>
webpack 打包多页面
查看>>
傻瓜式入门Redux
查看>>
最新图解 如何提升phpstudy中的mysql版本
查看>>
华山论剑之iOS&tableView的双剑合璧
查看>>
4K超清,2500万人在线,猫晚直播技术全解读
查看>>
编译时注解 ButterKnife源码分析和手写
查看>>
人人都能学会的python编程教程2:数据类型和变量
查看>>
iOS开发: CocoaPods远程私有仓库的维护-添加子库
查看>>