NaN 在 JSON 中被强制转为 null,因 JSON 规范仅允许有限数字,NaN 属无效计算状态,非合法数值;序列化后不可逆,需用额外字段或约定标识其原始语义。

NaN 在 JSON 序列化中不会保留原值,而是被统一转为 null —— 这不是浏览器或引擎的“bug”,而是 JSON 规范(RFC 7159)的强制要求。
为什么 NaN 不能出现在 JSON 中
JSON 只定义了六种合法原始类型:字符串、数字、布尔值、null、数组、对象。其中“数字”必须是可解析的十进制有限值,而 NaN 是 IEEE 754 中的特殊状态,不属于“数”的语义范畴,它代表“计算结果无效”,不是某个具体数值。
- 规范原文明确禁止:"Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted."
- 不同语言对 NaN 的内部表示和比较行为不一致(例如
NaN !== NaN),若允许序列化,接收方无法可靠还原或判断其原始意图 - JSON 的设计目标是跨语言互操作,不是完整映射 JS 运行时的所有特性
实际序列化行为:JavaScript 中的表现
调用 JSON.stringify({ x: NaN }) 得到的是 {"x":null},而非报错。同理,Infinity 和 -Infinity 也转为 null。
-
undefined、function、Symbol等会被静默忽略(键值对消失) -
NaN不会像undefined那样被跳过,而是显式替换为null,但丢失了“这是 NaN”的元信息 - 反序列化后得到的是真正的
null,无法区分它原本是null还是NaN
与 null 的关键区别
null 是 JSON 原生支持的合法值,语义清晰:表示“空值”或“缺失值”。而 NaN 是 JS 计算过程中的异常状态,二者在语义、规范地位和可恢复性上完全不同。
立即学习“Java免费学习笔记(深入)”;
-
null序列化前后保持一致,且所有 JSON 解析器都按相同方式处理 -
NaN → null是单向映射,不可逆;没有标准机制能从null推断出原始是NaN - 若业务逻辑需区分“空”和“无效计算”,应改用字段标记(如
{"value": null, "status": "invalid"})而非依赖NaN
替代方案建议
若必须传递 NaN 含义,需主动设计语义层,而非依赖默认序列化:
- 提前将
NaN显式转为null,并在文档或 schema 中说明该字段为null时代表“无效数值” - 使用额外字段标注状态,例如
{ "score": null, "scoreStatus": "nan" } - 在
replacer函数中拦截NaN,转为带标识的字符串(如"__NaN__"),但需配套反序列化解析逻辑,且注意接收方是否支持 - 避免在需要精确数值语义的场景(如金融、科学计算)中混用
NaN作为业务数据


















