Skip to content

语法与六种值:规范级细节

基于 RFC 8259 / ECMA-404 · JSON Schema 2020-12 · 核于 2026-07

速查

  • 六个结构字符[ ] { } : ,空白(空格/制表/换行/回车)可出现在任意两个 token 之间。
  • 对象{},键必双引号字符串,SHOULD 唯一;重复键行为未定义,多数实现保留最后一个
  • 数组[],有序、元素类型可异构,无尾逗号。
  • 字符串转义(仅这 8+1 种):\" \\ \/ \b \f \n \r \t\uXXXX(四位十六进制)。控制字符 U+0000–U+001F 必须转义。
  • \uXXXX 只编码一个 16 位码元;BMP 之外的字符(码点 > U+FFFF)用代理对(两个 \u,如 😀 = 😀),也可直接用 UTF-8 原样写。
  • 数值规则:十进制;无前导零007 ❌)、整数部分不可省.5 ❌)、无十六进制/八进制0xFF ❌)、NaN/Infinity;可负号、可小数、可指数 e/E6.022e23)。
  • 数字精度:互操作性只保证 IEEE 754 双精度范围;安全整数区间 [-(2^53−1), 2^53−1],超出即不可靠。
  • true / false / null:全小写字面量,大小写敏感。
  • 编码:跨系统交换 MUST 用 UTF-8MUST NOT 添加 BOM(U+FEFF),解析方 MAY 忽略已存在的 BOM。
  • 顶层:任意合法值(RFC 8259 放宽,不再限对象/数组)。
  • 无注释、无尾逗号——要这些能力去看 变体页

一、结构字符与空白

JSON 只有 6 个结构字符[ ](数组括号)、{ }(对象括号)、:(键值分隔)、,(元素/键值对分隔)。

空白(space U+0020、tab U+0009、换行 U+000A、回车 U+000D)可以插入在任意两个 token 之间——所以 JSON 可以紧凑成一行,也可以缩进美化,语义完全一致:

json
{"a":1,"b":[2,3]}

等价于

json
{
  "a": 1,
  "b": [2, 3]
}

只有这四种是空白

JSON 的「空白」严格限定为上述四个字符。其它 Unicode 空白(如不换行空格 U+00A0)不算 JSON 空白,出现在 token 之间会导致解析失败。

二、对象:键必双引号,重复键要警惕

对象是无序的键值对集合:

json
{ "name": "Ada", "age": 36, "tags": ["math", "cs"] }
  • 必须是双引号字符串(这是与 JS 字面量的核心差异)。
  • RFC 8259 规定对象内的名字 SHOULD(应当)唯一,但没有强制禁止重复。
  • 出现重复键时行为「未定义/不可预测」——实践中多数实现保留最后一个
js
JSON.parse('{"a":1,"a":2}'); // { a: 2 }  ← 保留最后一个

生产中应避免依赖重复键:不同解析器行为可能不同,还可能被利用制造解析歧义(一种安全隐患,如前后端对同一字段解读不一致)。

三、字符串与转义

字符串是双引号包裹的零或多个 Unicode 字符,用反斜杠转义。合法转义只有这些

转义含义
\"双引号
\\反斜杠
\/斜杠(可选转义,</script> 场景常用)
\b \f \n \r \t退格 / 换页 / 换行 / 回车 / 制表
\uXXXX四位十六进制指定的 Unicode 码元

控制字符必须转义

U+0000 到 U+001F 的控制字符(含真实换行、制表符)不能裸出现在字符串里,必须转义。所以 JSON 字符串里没有「多行字符串」——想换行只能写 \n

\u 与代理对(astral 字符)

\uXXXX 只能编码一个 16 位码元。对基本多文种平面(BMP)之外的字符(码点 > U+FFFF,如大部分 emoji),要用 UTF-16 代理对——两个 \u 转义拼成 12 字符序列:

json
{ "emoji": "😀" }   // 😀 U+1F600

因为 JSON 交换用 UTF-8,你也完全可以直接把字符原样写进去{ "emoji": "😀" } 同样合法,且更易读。\u 转义主要用于确保纯 ASCII 传输通道下也不丢字符。

四、数值:最容易踩的严格规则

JSON 数字「很像 C/Java 的数字,但不用八进制和十六进制」。语法要点:

-?  整数部分  (.小数部分)?  (e/E [+/-] 指数)?

允许0-13.14-0.56.022e231E-10

非法(常见坑):

写法为什么非法
007前导零不允许(0 后不能直接跟数字)
.5整数部分不可省略,须写 0.5
5.小数点后须有数字,须写 5.0
0xFF无十六进制
+1不允许显式正号
NaN / Infinity无法用数字语法表示,明确禁止

精度:双精度浮点与安全整数

RFC 8259 明确:良好互操作性建立在实现「不期望超过 IEEE 754 双精度(binary64) 的精度与范围」之上。这意味着:

  • 安全整数区间是 [-(2^53−1), 2^53−1](即 ±9007199254740991)。
  • 超出此范围的整数跨实现不可靠——JS 里会静默丢精度:
js
JSON.parse('{"id": 9999999999999999}').id; // 10000000000000000 ← 已失真

大整数(订单号、雪花 ID、区块链数值)应用字符串承载传输,前端按字符串或 BigInt 处理。详见 JS API 页

五、字面量:全小写

只有三个字面量名,且大小写敏感、必须全小写truefalsenullTrueFALSENullnilNone 全部非法。

六、编码与 BOM

  • 编码:RFC 8259 规定,在非封闭生态间交换的 JSON 文本 MUST 使用 UTF-8。(旧 RFC 4627 曾允许 UTF-16/32,已收敛。)这也是 application/json 媒体类型不带 charset 参数的原因。
  • BOM:实现 MUST NOT 在网络传输的 JSON 开头添加字节序标记(U+FEFF);接收方 MAY 忽略已存在的 BOM(不强制报错)。

BOM 是隐蔽坑

Windows 记事本另存的 UTF-8 常带 BOM,某些严格解析器会因此报错,或让第一个键名前多出不可见字符。跨系统传 JSON、读磁盘上的 .json 配置时,留意去掉 BOM。

七、无注释、无尾逗号

标准 JSON 不支持任何注释///* */ 都非法),也不允许尾逗号。这是它作为「机器交换格式」的刻意克制。要注释/尾逗号,请用 JSON5 或 JSONC


语法规则掌握后,进入 JS 中的 JSON APIJSON.parse 的 reviver、JSON.stringify 的 replacer/space/toJSON,以及 undefined/循环引用/Date/大整数/BigInt 一整套坑。