JsonConvert.DeserializeObject遇字符串含NaN时反序列化失败求助
解决Knockout序列化NaN导致后端JsonConvert反序列化失败的问题
这个问题很典型——ko.toJSON会把JavaScript里的NaN值序列化为字符串"NaN",但这不符合JSON官方规范(JSON只允许null、布尔值、数字、字符串、数组和对象这几种类型),而Newtonsoft.Json默认拒绝解析这种非法的JSON值,所以才会出现反序列化失败的情况。下面给你两种可行的解决方案,你可以根据场景选择:
方案一:前端处理(推荐,符合JSON规范)
直接在序列化阶段把NaN替换成合法的null,避免生成不符合规范的JSON。你可以通过以下两种方式实现:
方式1:用原生JSON.stringify代替ko.toJSON
ko.toJSON内部其实依赖JSON.stringify,但它的处理逻辑会保留NaN。你可以先把ViewModel转成普通JavaScript对象(用ko.toJS),再用原生JSON.stringify序列化——原生方法会自动把NaN和Infinity转成null:
// 先转成普通JS对象,再用原生序列化 var plainObj = ko.toJS(viewModel); var data = JSON.stringify(plainObj); $.ajax({ type: 'POST', url: '@Url.Action("Action")', data: { data: data }, dataType: 'json' // 其他配置... });
方式2:手动遍历替换NaN
如果需要更精细的控制,可以手动遍历ViewModel对象,把所有NaN值替换成null:
function cleanNaN(obj) { for (const key in obj) { if (obj.hasOwnProperty(key)) { const value = obj[key]; if (typeof value === 'number' && isNaN(value)) { obj[key] = null; } else if (typeof value === 'object' && value !== null) { cleanNaN(value); // 递归处理嵌套对象 } } } } var plainObj = ko.toJS(viewModel); cleanNaN(plainObj); var data = JSON.stringify(plainObj);
方案二:后端处理(快速解决,但依赖非标准JSON)
如果你不想修改前端代码,可以配置Newtonsoft.Json允许解析NaN值。只需要在反序列化的JsonSerializerSettings中添加AllowNaN = true:
var viewModel = JsonConvert.DeserializeObject<ViewModel>(data, new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Local, DateFormatHandling = DateFormatHandling.IsoDateFormat, AllowNaN = true // 允许解析JSON中的NaN值 });
⚠️ 注意:这种方案有个限制——ViewModel中对应的字段必须是double或float类型(因为decimal类型不支持NaN)。如果你的字段是decimal,还是建议用前端方案把NaN转成null,同时把后端字段改成可空的decimal?。
内容的提问来源于stack exchange,提问作者AGuyCalledGerald
相关产品推荐
相关产品推荐

