JSON 速查表

JSON 速查:数据类型、双引号与反斜杠转义、JSON.parse / stringify、MIME 类型、大整数精度与日期处理等常用语法与坑点,写接口或配置文件时快速查阅。

原理解析

JSON(JavaScript Object Notation)是轻量的数据交换格式,类型只有字符串、数字、对象、数组、布尔、null 六种。它源于 JS 字面量语法,但已成为语言无关的标准。

与 XML 相比 JSON 更紧凑、更易被程序解析。注意严格性:键与字符串必须用双引号、不能有尾随逗号、不能出现注释、数字不能 NaN/Infinity。它描述「数据」,不描述「样式」或「行为」。

什么时候该查这张表

这张表在你要确认 JSON 语法细节时有用。它按类型与语法(string、number、boolean、null、object、array)列出合法写法、含义与示例,并覆盖转义、嵌套深度等易错点。写接口文档或排查解析错误时查它。

不该查的情况:你在做 JSON 的 schema 设计、版本演进或与 GraphQL 的对比。表里的语法规则只回答什么是合法 JSON,不回答数据结构该怎么组织。

判断标准:注意 JSON 与 JavaScript 的差异。JSON 是数据格式,JavaScript 是编程语言,两者的字面量几乎不重合:JSON 没有 undefined、没有注释、尾随逗号非法、顶层可以是任何值而 JS 的对象字面量不能是数字。这些差异是跨语言解析出错的根源。

特别注意数字与字符串的边界:JSON 允许大整数但很多语言的解析器会把它当浮点导致精度丢失;反过来本该是数字的值写成字符串,后端会静默收到字符串类型而不报错。

边界与常见陷阱

  • 大整数在多数语言的解析器里会丢精度

    JSON 允许任意长度数字,但 JavaScript 的 JSON.parse 会把超过 2^53 的整数转成双精度浮点数,末尾有效位被静默截断。雪花 ID、订单号、金额分(以分为单位的大数)都受影响,而且不报错——数据看似正常但末几位变了。可行做法:把大整数当字符串传输(Snowflake ID 本身就常以字符串形式),或在解析前用支持任意精度的解析器。数据库侧也建议用字符串或 NUMERIC 存大数。

  • 尾随逗号在严格解析器里非法

    JSON 规范不允许尾随逗号,但很多编辑器与初学者写出来是带尾随逗号的数组字面量。JavaScript 解析器宽容能过,后端用 Python/Java 的严格解析器就直接报错,且报错位置常指向行尾而非真正的错误字符处。更麻烦的是同一份 JSON 文件在不同服务里表现不一致——本地测试通过、生产 500。写入侧应做规范化:出站前 JSON.stringify(它不会产生尾随逗号),入站接受前先校验。

  • JSON 注释与单引号是非法语法

    JSON 只支持双引号字符串、不支持注释。这些是 JavaScript 的习惯被带进来后最常见的两个错误来源。开发期可以用 JSON5 或带注释的 .jsonc 文件写配置,但传输层必须是纯 JSON。若确实需要给接口加说明,正规做法是用 schema 字段(如 description)或 OpenAPI 文档,而不是在 JSON 里塞注释。

与相邻内容的分工

要美化、校验或格式化 JSON,用站内 JSON 格式化工具;本页是语法对照表,不提供处理工具。

要了解 JSON Schema 的写法用于接口契约,属数据建模范畴,本表不覆盖。

要处理 JSON 与 YAML / TOML / XML 的取舍,属序列化选型范畴,需要按场景判断而非查表。

若目的是排查某个接口的解析失败,通常还要看实际报文与服务端解析器类型,单纯的语法表不足以定位。

实战片段

要点:① JSON 只认双引号、不支持注释、没有尾随逗号,这些 JavaScript 习惯会让严格解析器直接报错;② 超过 2^53 的整数在多数语言解析器里静默丢精度,大整数(雪花 ID、订单号、金额分)应按字符串传输;③ 本地测试通过不代表生产通过——同一份 JSON 在宽松与严格解析器下行为不同;④ 入站数据先校验再使用,同时过滤 __proto__ 键防原型污染;⑤ 出站用 JSON.stringify 规范化,它不会产生尾随逗号。

// ① 语法速查:合法 vs 常见错误
const ok = { s: "double only", n: 1e3, b: true, z: null, a: [1, 2] }
const bad = {
  // single: 'not valid JSON',      // ❌ 单引号
  // n1: 0800,                    // ❌ 非法数字(前导 0)
  // t: undefined,                // ❌ undefined 不存在
  // a: [1, 2, 3,],               // ❌ 尾随逗号
}
// console.log(JSON.stringify(bad))   // 注释被丢掉,undefined 被丢掉

// ② 🔴 大整数精度丢失(静默发生,不报错)
const big = '{"id":9007199254740993}'          // 2^53 + 1
const parsed = JSON.parse(big)
console.log(parsed.id)                         // 9007199254740992 ← 末位丢了
console.log(parsed.id === 9007199254740993n)   // false
// ✅ 方案:传字符串
console.log(JSON.parse('{"id":"9007199254740993"}').id)   // '9007199254740993'

// ③ 转义:控制字符与引号必须转义
const risky = { note: 'He said "hi"
and left' }
console.log(JSON.stringify(risky))
// {"note":"He said "hi"
and left"}   ← 正确转义

// ④ 解析前校验:别等运行时才发现格式错误
function parseJsonSafely(text) {
  try {
    const v = JSON.parse(text)
    if (v === null || typeof v !== 'object') {
      return { ok: false, error: '顶层必须是对象或数组' }
    }
    return { ok: true, value: v }
  } catch (e) {
    return { ok: false, error: String(e.message) }
  }
}
console.log(parseJsonSafely('{"a":1}'))        // { ok: true, ... }
console.log(parseJsonSafely('{"a":1,}'))       // { ok: false, ... }

// ⑤ 出站前规范化:stringify 不会产生尾随逗号
console.log(JSON.stringify({ a: 1, b: [1, 2] }, null, 2))

// ⑥ 深度解析与原型污染防护(来自不可信输入时)
const safe = JSON.parse(text, (k, v) => (k === '__proto__' ? undefined : v))

实践注解

  • JSON 不保证键序,但多数解析器保留插入序规范把对象定义为无序集合,所以不能把顺序当作契约;然而 JS 的 JSON.parse 与 Python 的 json 在实现上保留了插入顺序,容易让人误以为顺序有保证。依赖顺序的逻辑要显式排序。
  • 大整数会丢精度JS 的 number 是双精度浮点,超过 2^53-1 的整数(如雪花 ID、部分时间戳)在 JSON.parse 后会被舍入。接口传大整数应改用字符串,或在前端引入 BigInt 感知的解析方式。
  • JSON.parse 的报错信息几乎不告诉你位置SyntaxError: Unexpected token } 不会给出字符偏移,且行号常被规范化掉。排查大文件时先把内容压缩到单行、或用 JSON.parse 的 reviver/第三方解析器定位,效率更高。

数据来源

  • RFC 8259 (STD 90)
  • ECMA-404 (The JSON Data Interchange Syntax)

上述编号、名称与定义均来自公开规范,本站不主张对规范数据本身的独创性;本页的编排方式、中文释义与实践注解由本站撰写。

类型 / 语法说明示例
string双引号包裹的文本值"name": "Tom"
number整数或浮点数(无前导零,不含 NaN/Infinity)"age": 30
boolean布尔值 true 或 false"active": true
null表示空值(必须小写)"deleted": null
object无序键值集合,用花括号包裹{"id": 1, "name": "Tom"}
array有序值列表,用方括号包裹["a", "b", "c"]
"key"键必须是双引号字符串"key": value
escape \"字符串内的双引号需转义为 \""q": "He said \"hi\""
\\反斜杠本身需写成 \\(如路径 C:\\temp)"p": "C:/tmp"
\b \f \n \r \t控制字符用转义序列表示"s": "line1\nline2"
\uXXXXUnicode 码点用 \uXXXX 表示"s": "\u2728"
,键值对 / 数组元素之间用逗号分隔{"a": 1, "b": 2}
no trailing comma最后一项后不允许尾逗号✗ {"a": 1,}
no comments标准 JSON 不支持 // 或 /* */ 注释用 JSONC / JSON5 扩展
root value顶层可以是 object 或 array[1, 2, 3]
nested objectobject 的值可以是 object / array{"user": {"id": 1}}
nested arrayarray 可包含任意类型元素[1, "a", {"x": 2}]
duplicate keys解析时后者覆盖前者(应避免重复键){"a": 1, "a": 2} → 2
JSON.parse()字符串解析为对象,非法则抛错JSON.parse('{"a": 1}')
JSON.stringify()对象序列化为字符串JSON.stringify(obj, null, 2)
pretty / minify带缩进格式化 vs 去空白压缩JSON.stringify(o, null, 2)
application/json传输时使用该 MIME 类型Content-Type: application/json
JSON Schema声明式描述数据结构的格式{ "$schema": "...", "type": "object" }
big integer超过 2^53 的整数在 JS 中失真"id": 9007199254740993
datesJSON 无日期类型,用 ISO 8601 字符串"ts": "2026-08-29T00:00:00Z"
no leading zero数字不允许前导零(如 01)"n": 1
JSON vs YAMLYAML 允许注释/无引号/缩进;JSON 更严格、解析更快—
JSON vs XMLJSON 更轻量、嵌套天然;XML 有标签/属性/命名空间—

常见问题

JSON 和 JavaScript 对象有什么区别?

JSON 是纯数据格式:键必须双引号、值只能是 string/number/boolean/null/object/array,不能有函数、undefined、Date 对象或注释。JS 对象字面量更宽松(键可无引号、可含方法)。JSON.parse / JSON.stringify 在两者间转换。

为什么我的 JSON 解析报错?

最常见原因:键没加双引号、字符串用了单引号、出现尾逗号、包含注释、或数字写成 01 / NaN / Infinity。用 JSON 校验或格式化工具可快速定位出错行号。

大整数(如订单号)为什么会变样?

JavaScript 数字采用双精度浮点,超过 2^53(9007199254740992)的整数无法精确表示,解析后末几位失真。处理 ID 等大整数应作为字符串传输,或使用 BigInt / decimal 类库。

JSON 和 YAML 该选哪个?

人写的配置、Kubernetes 清单等用 YAML(可读、支持注释);API 传输、日志、NoSQL 存储用 JSON(解析快、生态广)。两者可以互相转换。