ASP.NET MVC项目升级NewtonJson至13.0.1后JSON部分字段丢失问题求助
问题根因排查
核心原因
Newtonsoft.Json在4.5.7版本修复了DefaultValueHandling配置和DataMember特性共同作用时的逻辑漏洞,你遇到的字段丢失是修复后符合预期的序列化行为,具体触发条件如下:
- 布尔值类型的默认值为
false,你的全局序列化配置开启了DefaultValueHandling.Ignore,代表所有值等于默认值的字段都会被跳过不序列化 - 你的
ProductSettingsViewModel中的DefaultSelected属性同时标注了[DataMember(EmitDefaultValue = false)],进一步加强了「默认值不输出」的规则 - 当
DefaultSelected的值为false时,序列化逻辑会直接过滤该字段,不会出现在返回的JSON结构中
4.5.6版本之所以正常,是因为该版本对值类型默认值的判断逻辑存在bug,即使字段值等于默认值也会强制输出,升级后bug修复,过滤逻辑正式生效。
关联影响
你前端使用的是Knockout.js框架,当JSON中不存在defaultSelected字段时,前端视图模型初始化时该属性的取值为undefined,调用option.defaultSelected()会返回空值,导致if判断永远不命中,和原有逻辑不符。
解决方案
你可以根据业务需求选择任意一种方案修复:
- 方案1:单独配置该字段强制输出,不影响全局序列化规则
给DefaultSelected属性加JsonProperty特性:[DataMember(EmitDefaultValue = false, IsRequired = false)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] public virtual bool DefaultSelected { get; set; } - 方案2:修改属性为可空布尔类型
可空布尔的默认值为null,只要你赋值为true/false都不属于默认值,会正常输出:[DataMember(EmitDefaultValue = false, IsRequired = false)] public virtual bool? DefaultSelected { get; set; } - 方案3:前端兼容处理
初始化视图模型时给字段加默认值,或者判断时做兼容:if (option.defaultSelected && option.defaultSelected()) { // 原有逻辑 } - 方案4:修改全局序列化配置(不推荐,会影响所有接口的字段输出逻辑)
把全局配置的DefaultValueHandling.Ignore改为DefaultValueHandling.Include。
内容的提问来源于stack exchange,提问作者Shan Liang
相关产品推荐
相关产品推荐

