.NET Framework 4.5 WebApi中Newtonsoft.Json序列化忽略JsonProperty特性问题
问题原因
这个问题在.NET Framework 4.5的WebApi项目中非常常见,按出现概率从高到低,原因如下:
- Newtonsoft.Json程序集加载冲突
这是占比最高的诱因:代码里标记属性用的JsonPropertyAttribute,和执行序列化逻辑的JsonConvert,来自不同版本甚至不同发布方的Newtonsoft.Json程序集。
.NET Framework项目中很多第三方依赖会自带不同版本的Newtonsoft.Json,一旦web.config里的程序集绑定重定向配置有误,就会出现写代码时引用的是高版本的JsonPropertyAttribute,运行时执行序列化的却是低版本的JsonConvert。两边的特性类型不属于同一个程序集,序列化器根本识别不到属性上标记的配置,自然会按默认规则输出原属性名Workflow。
排查时可以在序列化代码行加断点,分别查看typeof(JsonPropertyAttribute).Assembly.FullName和typeof(JsonConvert).Assembly.FullName的值,如果两者版本号、公钥标记不一致,就能确认是这个问题。修复时统一解决方案内所有项目的Newtonsoft.Json引用版本,修正web.config下runtime节点的程序集绑定重定向规则,保证运行时进程只加载同一个版本的Newtonsoft.Json即可。 - 自定义契约解析器覆盖了特性逻辑
如果你之前给JsonConvert.DefaultSettings赋值过全局默认序列化配置,或是在WebApi全局配置中注册了自定义IContractResolver(比如常见的全局驼峰命名解析器),且自定义解析器的逻辑是直接按规则生成属性名、没有读取属性上的JsonProperty特性配置,就会导致标记的特性失效。
要注意:哪怕手动调用JsonConvert.SerializeObject时显式传入了JsonSerializerSettings,只要没有给Settings的ContractResolver属性显式赋值,全局配置的契约解析器依然会生效。 - 序列化对象的实际类型和定义类型不符
如果传入序列化方法的是类A的子类实例,且子类通过new关键字隐藏了父类的Workflow属性,同时子类的属性没有加JsonProperty特性,序列化器会按子类的属性定义生成结果,父类上标记的特性不会生效。 - 编译后特性元数据丢失
极少数场景下,如果项目接入了AOP编译织入工具(比如旧版PostSharp)、或是开启了特殊编译优化选项,可能导致编译后程序集里属性上的JsonProperty特性被擦除,序列化器自然无法读取到对应的命名配置。
内容的提问来源于stack exchange,提问作者michasaucer
相关产品推荐
相关产品推荐

