JSON 工具箱

NaN 和 Infinity 能放进 JSON 吗

结论:JSON 只有十进制数字字面量,没有 NaN、Infinity、-Infinity。JSON.stringify 会静默把它们变成 null,接口里因此出现过大量「明明是数字却收到 null」的故障。

入门约 3 分钟发布于 2026-10-30更新于 2026-10-30
NaN 与 Infinity 在 JSON 中的实际行为

结论:不能。JSON 只允许十进制数字字面量,JSON.stringify 会把 NaN 和 Infinity 静默序列化成 null;要表达这类状态,用 null 加一个说明原因的状态字段,或使用带明确约定的字符串。

JSON.stringify({ ratio: NaN, limit: Infinity });
// '{"ratio":null,"limit":null}'

没有任何报错,也没有任何警告,两个值直接变成了 null。这是最容易在生产环境里埋雷的一类转换。

标准里为什么没有

RFC 8259 的数字语法是:

number = [ minus ] int [ frac ] [ exp ]

只认十进制字面量。NaN、Infinity 是 IEEE 754 的特殊值,不是数字字面量;把它们写进 JSON 文本,解析器会当成非法标识符。 JSON 的设计目标之一是跨语言可解析,而这些特殊值在不同语言里的表示、比较语义都不一致,干脆排除在外。

各语言的实际行为

语言 行为
JavaScript JSON.stringify 静默转成 null
Python json.dumps 默认输出 NaN(非标准),allow_nan=False 时抛 ValueError
Go encoding/json 序列化时报错 unsupported value: NaN
Java Jackson 默认输出 "NaN" 字符串,可配置为抛错

同一个值,四种行为。跨语言接口出现「数字字段偶尔是 null」时,先怀疑这一层。

该用什么表达

方案一:字符串约定。 用 "NaN"、"Infinity" 加类型说明,消费方显式判断。缺点是把类型判断推给了每个调用方。

方案二:null + 状态字段。 更推荐的做法:值不可用时给 null,另加一个字段说明原因,例如 {"avgLatency": null, "avgLatencyStatus": "no-sample"}。语义清楚,也便于统计。

方案三:换个单位。 很多「除零得到 Infinity」的场景,本质是没有样本。直接返回 null 并让前端显示「暂无数据」,比传一个无穷大更接近业务事实。

方案四:整数化。 如果是精度问题导致的 NaN(比如 0/0、Infinity - Infinity),在计算前就做防御,别让脏值流到序列化这一步。

顺手检查

  • 前端把 JSON.parse 结果直接喂给图表库,null 会让折线断开——要确认这是预期行为
  • JSON.stringify 还会丢掉 undefined、函数、Symbol,对象的这些键会整个消失,不是变成 null
  • 后端用 Python 的 json.dumps 且 allow_nan 为默认 True,产出的就不是标准 JSON,浏览器 JSON.parse 会失败

常见问题

遇到「数字字段收到 null」应该怎么排查?

先确认该字段在序列化前是不是 NaN 或 Infinity。JavaScript 的 JSON.stringify 会把这两种特殊浮点静默转成 null,Go 会直接报错,Python 默认则输出非标准的 NaN。

是否可以用字符串 "NaN" 表示特殊值?

可以,但要配上明确的类型约定,让每个消费方显式判断。更稳妥的做法是值不可用时给 null,另加一个状态字段说明原因。

相关工具

延伸阅读