认识k_BackingField

本文探讨了在C#中使用DataContractJsonSerializer进行JSON序列化时遇到的一个问题:当实体类使用自动属性并标记为Serializable时,生成的JSON会出现k_BackingField前缀。文章通过对比不同属性定义方式,提出了使用DataMember特性解决此问题的方法。

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

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

JsonHelper

 

不过使用该类库方法的过程中还是不慎意外发现了k_BackingField

举例之前说一下我们的一个简单的实体类Person,它有如下定义:

Person

 

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

Test

 

而且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前缀,那传统那种属性的写法呢?

Person

 

OK,我们想一块去了,经测试,带Serializable特性的Person类,输出json一点问题没有:

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

 

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

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

Person

 

json输出带有k_BackingField前缀的问题可能非常简单,这里只是善意地提醒,我个人曾经有过“惨痛”的教训,而且感觉还相当隐蔽,大家也要小心啊。

最后,在使用.net framework自带的json有关类库的时候还碰到过特殊符号和时间格式转换的问题,网上有不少文章都讲到,相信不少人也有类似经历,这里就不说了。





本文转自JeffWong博客园博客,原文链接:http://www.cnblogs.com/jeffwongishandsome/archive/2012/05/31/2529196.html,如需转载请自行联系原作者


Renamed Types: [Ob]Ob.Controllers.WeatherForecastController/<>c -> [Ob]Ob.Controllers.WeatherForecastController/  { [Ob]Ob.Controllers.WeatherForecastController/<>c::<Get>b__3_0[1]( [System.Runtime]System.Int32 ) ->   [Ob]Ob.Controllers.WeatherForecastController/<>c::<Get2>b__4_0[1]( [System.Runtime]System.Int32 ) ->   [Ob]Ob.Controllers.WeatherForecastController/<>c::.cctor[0]( ) skipped: special name [Ob]Ob.Controllers.WeatherForecastController/<>c::.ctor[0]( ) skipped: special name Ob.Controllers.WeatherForecastController/<>c [Ob]Ob.Controllers.WeatherForecastController/<>c Ob.Controllers.WeatherForecastController/<>c::<>9 ->   System.Func`2<System.Int32,Ob.WeatherForecast> [Ob]System.Func`2<System.Int32,Ob.WeatherForecast> Ob.Controllers.WeatherForecastController/<>c::<>9__3_0 ->   System.Func`2<System.Int32,Ob.WeatherForecast> [Ob]System.Func`2<System.Int32,Ob.WeatherForecast> Ob.Controllers.WeatherForecastController/<>c::<>9__4_0 ->   } [Ob]Program -> [Ob] .  { [Ob]Program::<Main>$[1]( [System.Runtime]System.String[] ) ->   [Ob]Program::.ctor[0]( ) skipped: special name } Skipped Types: [Ob]Ob.WeatherForecast skipped: KeepPublicApi option in configuration { [Ob]Ob.WeatherForecast::get_Date[0]( ) skipped: skip by property [Ob]Ob.WeatherForecast::set_Date[1]( [System.Runtime]System.DateOnly ) skipped: skip by property [Ob]Ob.WeatherForecast::get_TemperatureC[0]( ) skipped: skip by property [Ob]Ob.WeatherForecast::set_TemperatureC[1]( [System.Runtime]System.Int32 ) skipped: skip by property [Ob]Ob.WeatherForecast::get_TemperatureF[0]( ) skipped: skip by property [Ob]Ob.WeatherForecast::get_Summary[0]( ) skipped: skip by property [Ob]Ob.WeatherForecast::set_Summary[1]( [System.Runtime]System.String ) skipped: skip by property [Ob]Ob.WeatherForecast::.ctor[0]( ) skipped: special name System.DateOnly [Ob]System.DateOnly Ob.WeatherForecast::<Date>k__BackingField ->   System.Int32 [Ob]System.Int32 Ob.WeatherForecast::<TemperatureC>k__BackingField ->   System.String [Ob]System.String Ob.WeatherForecast::<Summary>k__BackingField ->   System.DateOnly [Ob]System.DateOnly Ob.WeatherForecast::Date skipped: KeepPublicApi option in configuration System.Int32 [Ob]System.Int32 Ob.WeatherForecast::TemperatureC skipped: KeepPublicApi option in configuration System.Int32 [Ob]System.Int32 Ob.WeatherForecast::TemperatureF skipped: KeepPublicApi option in configuration System.String [Ob]System.String Ob.WeatherForecast::Summary skipped: KeepPublicApi option in configuration } [Ob]Ob.Controllers.WeatherForecastController skipped: KeepPublicApi option in configuration { [Ob]Ob.Controllers.WeatherForecastController::.ctor[1]( [Microsoft.Extensions.Logging.Abstractions]Microsoft.Extensions.Logging.ILogger`1<[Ob]Ob.Controllers.WeatherForecastController> ) skipped: special name [Ob]Ob.Controllers.WeatherForecastController::Get[0]( ) skipped: method rule in configuration [Ob]Ob.Controllers.WeatherForecastController::Get2[0]( ) skipped: KeepPublicApi option in configuration [Ob]Ob.Controllers.WeatherForecastController::.cctor[0]( ) skipped: special name System.String[] [Ob]System.String[] Ob.Controllers.WeatherForecastController::Summaries ->   Microsoft.Extensions.Logging.ILogger`1<Ob.Controllers.WeatherForecastController> [Ob]Microsoft.Extensions.Logging.ILogger`1<Ob.Controllers.WeatherForecastController> Ob.Controllers.WeatherForecastController::_logger ->   } Renamed Resources: Skipped Resources: 看不懂
最新发布
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值