JSON 的语法规则很简单。数据类型有 6 种,容器结构只有对象和数组两种,加上几条规则就覆盖了所有情况。但手写时还是经常出错,原因通常是习惯了 JavaScript 或 Python 那种更宽松的写法。这篇文章把 JSON 里 6 种数据类型的写法和语法规则整理出来,每个都配代码示例。
JSON 语法由 RFC 8259在新标签页中打开 和 ECMA-404在新标签页中打开 两份规范定义,两者的语法定义完全一致。本文用实际例子讲解这些规则,同时覆盖手写 JSON 时最常见的错误模式和解决办法。
想了解 JSON 是什么,以及它和 XML、CSV、YAML 等其他数据格式有什么区别,可以参考 JSON 是什么。
想检查你写的 JSON 是否符合规范,可以粘贴到 FormatArc JSON 格式化器 里。语法错误会带行号即时显示,所有处理都在浏览器内完成,数据不会发送到任何服务器。
字符串(String)
字符串必须用双引号 " 包裹。单引号 ' 和反引号在 JSON 标准中不能使用。
{
"greeting": "你好",
"empty": ""
}
转义序列
字符串里需要包含特殊字符或控制字符时,用反斜杠(\)转义。
| 写法 | 含义 |
|---|---|
\" | 双引号 |
\\ | 反斜杠 |
\/ | 斜杠(转义是可选的) |
\b | 退格(Backspace) |
\f | 换页(Form feed) |
\n | 换行(Line feed) |
\r | 回车(Carriage return) |
\t | 制表符(Tab) |
\uXXXX | 4 位十六进制 Unicode 码点 |
{
"path": "C:\\Users\\Documents",
"message": "第一行\n第二行",
"quote": "他被称为\"专家\""
}
漏掉反斜杠转义是最常见的语法错误之一。尤其是 Windows 文件路径或正则表达式字符串里的 \,必须写成 \\。
U+0000 到 U+001F 的控制字符不能直接放在字符串里,必须转义。直接写制表符或换行符会导致解析错误,应该用 \t 和 \n。
Unicode 表示
JSON 默认使用 UTF-8 编码,所以中文、日文、emoji 都可以直接写在字符串里。遇到难以输入的特殊符号或需要规避编码问题时,可以用 \uXXXX 格式转义。
{
"direct": "你好",
"escaped": "\u4f60\u597d"
}
数字(Number)
数字直接写,不加引号。整数、小数(浮点数)、负数、指数表示法(e/E)都支持。
{
"integer": 42,
"negative": -10,
"decimal": 3.14,
"exponent": 1.5e3
}
1.5e3 表示 1500。处理科学计算数据或大单位数值时会用到。
写数字时注意以下限制:
- 前导零(Leading zero)不允许,
007、012等应写7、12 - 不支持十六进制(
0xFF)或八进制(0o77)表示 - 小数点前后不能省略数字(
.5和42.都不行,要写0.5、42.0) NaN(Not a Number)和Infinity不是 JSON 标准数字,解析时会报错
// 以下都是 JSON 中无效的数字写法
007
NaN
Infinity
.5
(注:标准 JSON 没有注释语法,上面的 // 只是为了说明。)
大整数的精度限制
JSON 规范本身没有规定数字的精度上限,但实际使用中的大多数解析器(包括 JavaScript 内置的 JSON.parse)使用 IEEE 754 双精度浮点数来解析数字。
这意味着超过 $2^{53}$(= 9,007,199,254,740,992)的 64 位整数在解析过程中低位会被四舍五入,产生精度损失。
所以在处理 Twitter/X 的 snowflake ID、Discord ID、数据库 64 位整型主键这类超大数字的 API 中,用字符串包裹而不是直接传数字是标准做法。
{
"safe_id": 9007199254740991,
"snowflake_id": "9007199254740993"
}
客户端 JSON.parse 之后如果要无损处理 64 位整数,先以字符串形式接收再用 BigInt 等转换是安全的方式。
布尔值(Boolean)
只有 true 和 false 两个值,必须全部小写。
{
"isActive": true,
"isDeleted": false
}
True、FALSE、yes、no、1、0 都不是 JSON 的布尔值。从 Python(True/False)或 YAML(yes/no)复制数据时容易犯这个错。YAML 的语法规则和 JSON 差别不小,想了解 YAML 怎么写可以参考 YAML 语法指南。
null
表示值不存在或为空时用 null。和布尔值一样,必须全部小写。
{
"middleName": null,
"deletedAt": null
}
空字符串 "" 和 null 含义不同。需要区分"有值但内容为空"和"值本身不存在"时,用 null。JavaScript 的 undefined、Python 的 None、Ruby 的 nil 在 JSON 中都不存在,统一用 null 表示。
数组(Array)
用方括号 [] 包裹,各元素用逗号 , 分隔。数组是有序的值列表。
{
"colors": ["red", "green", "blue"],
"scores": [85, 92, 78],
"flags": [true, false, true]
}
空数组也合法。
{
"items": []
}
语法上允许在一个数组里混放不同数据类型。
["text", 42, true, null]
但实际工作中,一个数组里只放同一种类型的数据是惯例。混入不同类型会让接收方处理数据的逻辑变得复杂。
对象(Object)
用花括号 {} 包裹,键: 值 对用逗号 , 分隔。键必须是双引号包裹的字符串。
{
"id": 1,
"name": "产品A",
"price": 1500
}
空对象也是合法的 JSON。
{
"metadata": {}
}
JSON 规范中对象没有键的顺序。{"a": 1, "b": 2} 和 {"b": 2, "a": 1} 语义上等价。虽然大多数解析器实际会保持插入顺序,但不应编写依赖键顺序的逻辑。
关于键重复的注意事项
JSON 标准规范并没有严格禁止同一对象内键重复,但处理重复键的方式因解析器库而异。
{
"name": "Alice",
"name": "Bob"
}
大多数解析器会用后面定义的值(Bob)覆盖,但也有保留第一个值(Alice)的,也有直接报解析错误的。要保证系统间的互操作性,就不要在对象里创建重复键。
嵌套结构(Nesting)
JSON 强大的表达能力来自对象和数组可以自由嵌套。
对象里嵌套对象
需要分层组织相关配置或详细信息时使用。
{
"user": {
"name": "张三",
"contact": {
"email": "zhangsan@example.com",
"phone": "138-0000-0000"
}
}
}
数组里嵌套对象
返回 REST API 响应或数据库查询结果列表时最常用的模式。
{
"users": [
{
"id": 1,
"name": "张三",
"role": "admin"
},
{
"id": 2,
"name": "李四",
"role": "editor"
}
]
}
对象里嵌套数组
一个数据项包含多个子标签或列表时很实用。
{
"order": {
"id": "ORD-2026-001",
"items": [
{ "product": "笔记本电脑", "quantity": 1 },
{ "product": "无线鼠标", "quantity": 2 }
],
"tags": ["urgent", "electronics"]
}
}
嵌套超过 4 到 5 层时,人眼难以阅读,代码中访问路径也会变长。嵌套过深时建议考虑能否将数据模型扁平化。
JSON 顶层(根)元素
JSON 文档的顶层(Root)通常是对象 {} 或数组 []。
按 RFC 8259 标准规范,字符串("hello")、数字(42)、布尔值(true)、null 等单一原始值也可以作为顶层元素,但实际生成和交换的 JSON 文档几乎都以对象或数组开头。
{
"status": "success",
"code": 200
}
[1, 2, 3, 4, 5]
空白字符与压缩格式
JSON 解析器会忽略标记之间的空白字符(空格、制表符、换行)。因此下面三种形式在语法上完全等价。
压缩(Compact)格式:
{"name":"张三","age":30}
格式化(Formatted)格式:
{
"name": "张三",
"age": 30
}
不规则空白格式:
{
"name" : "张三" ,
"age" : 30
}
网络传输或节省存储空间时,去掉多余空白的压缩格式更有优势;开发者需要查看或编辑配置时,带缩进的格式化格式可读性好得多。
常见语法错误
手写或修改 JSON 时经常出现的错误模式整理如下。
1. 尾逗号(Trailing Comma)
{
"a": 1,
"b": 2,
}
对象或数组最后一个元素后面的逗号在 JSON 标准中不允许。JavaScript、TypeScript、Python 代码中常常允许尾逗号,从这些语言复制粘贴时最容易出错(产生 Unexpected token } 错误)。具体原因和删除步骤可以参考 JSON 尾随逗号错误的修复方法。
2. 使用单引号
{'name': '张三'}
JSON 中键和字符串值都必须用双引号 "。单引号 ' 是语法错误。
3. 键省略引号
{name: "张三"}
JavaScript 对象字面量中允许不加引号的键,但 JSON 中键必须用双引号包裹。
4. 写注释
{
// 这条注释会导致语法错误
"name": "张三"
}
标准 JSON 规范没有注释语法。写 //、/* */、# 都会被解析器直接拒绝。需要注释的配置文件中应使用支持 JSONC 或 JSON5 扩展格式的环境。替代方案可以参考 JSON 可以写注释吗。
5. 使用 undefined 和 NaN
{
"value": undefined,
"result": NaN
}
JavaScript 的 undefined 和 NaN 不是 JSON 标准值。没有值的状态用 null 表示,数值计算失败用 null 或字符串 "NaN" 表示。
6. 没有引号的独立字符串
hello
没有引号的普通单词不是合法 JSON。要作为字符串使用就写成 "hello"。这些报错的更多原因和修复方法可以参考 JSON parse 报错排查。
快速参考
JSON 中所有可用数据类型及注意事项一览表。
| 数据类型 | 示例 | 书写注意事项 |
|---|---|---|
| 字符串(String) | "你好" | 必须用双引号 "。控制字符需 \ 转义 |
| 数字(Number) | 42, 3.14, -10, 1.5e3 | 不允许前导零、十六进制、NaN·Infinity |
| 布尔值(Boolean) | true, false | 仅小写有效(True、FALSE 无效) |
| null | null | 仅小写有效(None、undefined 无效) |
| 对象(Object) | {"key": "value"} | 键必须是双引号字符串。禁止尾逗号 |
| 数组(Array) | [1, 2, 3] | 方括号,元素间逗号分隔。禁止尾逗号 |
JSON 格式化与语法校验
JSON 写完后,交给解析器之前先过一遍语法校验比较稳妥。缺括号、漏转义、尾逗号等问题在大文件里靠肉眼很难找到。
FormatArc JSON 格式化器 一次粘贴就能同时完成缩进格式化和语法有效性检查。有语法错误时会明确标出出错行号与原因。
在终端或命令行环境中快速校验时,可以用以下命令:
# 使用 Python 标准库
python3 -m json.tool < file.json
# 使用 jq 工具
jq . file.json
两个工具在语法正确时都会输出格式化好的结果,有语法错误时会提示出错位置。想让 JSON 更好读,可以参考 JSON 排版工具。在终端里用 curl 获取 API 响应后想格式化 JSON 的话,方法可以参考 curl JSON 格式化。
JSON 书写惯例
JSON 语法本身是固定的,但为了便于操作有一些惯例:
- 缩进用 2 个空格最为普遍
- 结构相似的对象之间,键的顺序保持一致
- 键名统一用 camelCase 或 snake_case
- 能用扁平结构表达的就避免深层嵌套
常见问题
JSON 里能写注释吗?
不能。标准 JSON 规范(RFC 8259)中不包含 //、/* */、# 等注释语法。如果配置文件里需要注释,可以使用支持 JSONC 或 JSON5 扩展规范的软件,或者采用 "_comment": "说明内容" 这样的惯例假键方式。
JSON 最后一个元素后面能加逗号吗?
不能。在对象或数组最后一个元素后面加逗号,几乎所有 JSON 解析器都会报语法错误(SyntaxError)。从编程语言数组字面量复制过来时要特别注意。
JSON 的键必须用双引号包裹吗?
是,必须用双引号包裹。JavaScript 对象那样写 {name: "Alice"} 或者用单引号写 {'name': 'Alice'} 都不是合法 JSON。必须写成 {"name": "Alice"} 的形式。
JSON 解析报错时怎么快速定位位置?
把内容粘贴到 FormatArc JSON 格式化器会显示出错行号和错误消息。终端环境下也可以用 python3 -m json.tool < file.json 命令即时查看带行号的错误。
总结
- 字符串必须用双引号
"包裹,特殊字符用反斜杠(\)转义 - 数字直接写,不加引号。前导零、
NaN、Infinity不允许 - 超过 $2^{53}$ 的 64 位整数 ID 为避免精度损失,建议用字符串传递
- 布尔值(
true、false)和null必须全部小写 - 对象
{}的键始终是双引号字符串 - 数组
[]和对象{}最后一个元素后面不留尾逗号(trailing comma) - 写完 JSON 后在浏览器中用格式化器做语法校验,确保无误后再交给下游解析

