
为什么 JSON 语法如此严格
如果你曾见过 SyntaxError: Unexpected token < in JSON at position 0 或 JSON.parse: unexpected character,你就会知道 JSON 错误有多令人沮丧。与 HTML 或 CSS 不同(浏览器会尝试恢复),JSON 解析器是零容忍的:一个放错位置的逗号或一个未加引号的键就会导致整个解析失败。
本指南将介绍每个常见的 JSON 错误、其原因以及如何在一分钟内修复。

7 个最常见的 JSON 解析错误
1. 尾逗号
JSON 不允许在数组或对象的最后一个元素后面加逗号。这是最常见的错误——在 JavaScript 对象中是有效的,所以开发者习惯性地写出来。
// ❌ 无效
{
"name": "Alice",
"age": 30,
}
// ✅ 有效
{
"name": "Alice",
"age": 30
}
错误消息: SyntaxError: Unexpected token } in JSON(解析器遇到 } 时期望另一个键值对)
2. 未加引号的键
JSON 要求每个键都用双引号括起来。JavaScript 对象允许裸键({name: "Alice"}),但这在 JSON 中无效。
// ❌ 无效
{ name: "Alice" }
// ✅ 有效
{ "name": "Alice" }
错误消息: SyntaxError: Unexpected token n in JSON at position 2
3. 单引号代替双引号
JSON 中只允许双引号。单引号字符串在某些编辑器中可能不会报错,但在解析时会失败。
// ❌ 无效
{ "name": 'Alice' }
// ✅ 有效
{ "name": "Alice" }

4. JSON 中的注释
JSON 没有注释语法。// 和 /* */ 都是无效的。如果你需要带注释的配置文件,请改用 YAML 或 TOML。
// ❌ 无效
{
// 这是用户记录
"name": "Alice"
}
如果你使用 JSON 作为配置并希望添加注释,可以考虑 JSON5 或转换为 YAML。
5. undefined、NaN 或 Infinity 值
JSON 只支持以下值类型:字符串、数字、布尔值(true/false)、null、数组和对象。JavaScript 特有的值如 undefined、NaN 和 Infinity 在 JSON 中无效。
// ❌ 无效
{ "score": NaN, "ratio": Infinity, "data": undefined }
// ✅ 有效——使用 null 表示缺失值
{ "score": null, "ratio": null, "data": null }
在 JavaScript 中: JSON.stringify({a: undefined}) 会静默删除该键。JSON.stringify({a: NaN}) 输出 {"a":null}。在往返传输数据之前要了解这一点。
6. 响应中出现意外的 HTML 或纯文本
Unexpected token < in JSON at position 0 意味着你的 JSON 解析器收到了一个 HTML 页面而不是 JSON——< 是 <!DOCTYPE html> 或错误页面的开头。
这种情况发生在:
- 你的 API 端点返回了带有 HTML 内容的 HTTP 错误页面(404、500)
- 反向代理或 CDN 拦截了请求并返回了自己的错误页面
- 你访问了错误的 URL(缺少基本路径、多余斜杠)
// 调试:在解析之前记录原始响应文本
const res = await fetch('/api/data');
const text = await res.text();
console.log(text); // 查看实际获取的内容
const data = JSON.parse(text); // 现在解析
在解析之前,始终检查 res.status 和 res.headers.get('content-type')。
7. 字符串中未转义的特殊字符
JSON 字符串中的某些字符必须用反斜杠转义。字符串值中的原始换行符或制表符是无效的。
// ❌ 无效——字符串中的原始换行符
{ "message": "Hello
World" }
// ✅ 有效——转义后的换行符
{ "message": "Hello\nWorld" }
必须转义的字符:"、\ 和控制字符(\n、\r、\t、\b、\f)。Unicode 转义(\uXXXX)是可选的但有效。

快速参考:JSON 值规则
| 类型 | 有效示例 | 无效示例 |
|---|---|---|
| 字符串 | "hello", "" |
'hello', 裸词 |
| 数字 | 42, 3.14, -7, 1e10 |
NaN, Infinity, 0xFF |
| 布尔值 | true, false |
True, TRUE, yes |
| 空值 | null |
None, undefined, nil |
| 数组 | [1, 2, 3] |
[1, 2, 3,] (尾逗号) |
| 对象 | {"k": "v"} |
{k: "v"} (未加引号的键) |
如何快速验证 JSON
在线: 将你的 JSON 粘贴到 JSON Formatter 中——它会高亮显示错误发生的具体行和字符。
Node.js:
try {
const data = JSON.parse(yourString);
} catch (e) {
console.error('Parse error at:', e.message);
// "Unexpected token , in JSON at position 45"
}
Python:
import json
try:
data = json.loads(your_string)
except json.JSONDecodeError as e:
print(f"Error at line {e.lineno}, col {e.colno}: {e.msg}")
命令行(jq):
echo '{"name": "Alice",}' | jq .
# parse error: Invalid numeric literal at line 1, column 20
修复来自外部源的 JSON
当你从 API、配置文件或数据库导出中收到无法解析的 JSON 时:
- 检查 HTTP 响应状态——200 状态码并不保证返回的是 JSON 内容
- 检查
Content-Type——应为application/json - 在解析之前记录原始字符串——
console.log(rawText.slice(0, 200)) - 通过 linter 运行——JSON Formatter 会显示确切的错误位置
- 查找 BOM——某些工具会在开头添加 UTF-8 字节顺序标记(
\uFEFF),这在旧环境中会破坏JSON.parse
为什么 JSON 设计得如此严格
JSON 的严格性是一个特性。由于规范明确,在 Go、Python、JavaScript、Rust 或 Java 中解析的 JSON 字符串会产生相同的数据结构。如果允许尾逗号或注释,每个解析器都必须决定如何处理边缘情况,互操作性将受到影响。
如果你想要一个更宽松的配置文件格式,可以考虑 YAML(允许注释、多行字符串、锚点)或 TOML(专门为人类可编辑的配置设计)。对于服务之间的数据交换,JSON 的严格性正是你所需要的。
→ 使用 JSON Formatter 验证和格式化你的 JSON——它会高亮显示错误并带有行号,同时自动缩进有效的 JSON。