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" |
| \uXXXX | Unicode 码点用 \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 object | object 的值可以是 object / array | {"user": {"id": 1}} |
| nested array | array 可包含任意类型元素 | [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 |
| dates | JSON 无日期类型,用 ISO 8601 字符串 | "ts": "2026-08-29T00:00:00Z" |
| no leading zero | 数字不允许前导零(如 01) | "n": 1 |
| JSON vs YAML | YAML 允许注释/无引号/缩进;JSON 更严格、解析更快 | — |
| JSON vs XML | JSON 更轻量、嵌套天然;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(解析快、生态广)。两者可以互相转换。