FormatArc 简体中文版 JSON 格式化工具解析移除尾随逗号后的 JSON 结果FormatArc 简体中文版 JSON 格式化工具解析移除尾随逗号后的 JSON 结果
作者: FormatArc 编辑部发布日期: 2026-09-02更新日期: 2026-09-02

JSON 尾随逗号导致解析不合法:定位括号位置并删除

JSON 尾随逗号 — 先说结论

尾随逗号(trailing comma)是对象或数组最后一个元素后面、闭合括号 }] 前面残留的那个逗号。标准 JSON(RFC 8259)不允许尾随逗号,所以严格的解析器会报 Unexpected token }Expecting property name enclosed in double quotes 这样的错误,直接拒绝解析。修复方法就是把那个逗号删掉。

这篇文章只讲尾随逗号(,),不讲 ///* */ 注释。如果你真正想问的是 JSON 里能不能写注释,那是另一个话题。这里聚焦在多余的逗号上:为什么会报错、怎么找到它、怎么删掉它、JSON5 和 JSONC 有什么区别。

在浏览器里直接修复

如果你只是想让报错消失,不需要手动数字符位置。

  1. 打开 JSON 格式化工具
  2. 把出错的 JSON 粘贴进去
  3. 读报错行。它指向的是多余逗号后面那个闭合括号
  4. 删掉那个 }] 前面的逗号,再点一次运行
  5. 从输出里复制格式化好的合法 JSON

格式化全程在浏览器里完成。粘贴进去的 JSON 不会被上传、不会被记录、不会被保存。处理 API 响应或包含内部数据的配置文件时,这一点很重要。

FormatArc JSON 格式化工具展示格式化后的 JSON 结果FormatArc JSON 格式化工具展示格式化后的 JSON 结果

修复前后对比

尾随逗号出现在三种位置。下面分别给出出错示例和修复后的对照。

对象里的尾随逗号:

{
  "name": "Aoi",
  "role": "Engineer",
}
{
  "name": "Aoi",
  "role": "Engineer"
}

数组里的尾随逗号:

[
  "red",
  "green",
  "blue",
]
[
  "red",
  "green",
  "blue"
]

嵌套情况 — 内层对象或数组里藏着尾随逗号:

{
  "tags": ["a", "b",],
  "meta": {
    "active": true,
  }
}
{
  "tags": ["a", "b"],
  "meta": {
    "active": true
  }
}

不管哪种情况,修复方法都一样:删掉最后一个值和闭合括号之间的那个逗号。值本身没有问题。

报错信息长什么样

同样是尾随逗号,不同语言的解析器给出的措辞不同。

浏览器和 Node.js(V8)的 JSON.parse

SyntaxError: Unexpected token } in JSON at position 42
SyntaxError: Expected double-quoted property name in JSON at position 42

Python 的 json.loads

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 4 column 1 (char 42)

共同点是:解析器读到逗号后,期待后面还有另一个值或键,结果等来的是闭合括号。大多数解析器报告的 position 或行号指向的是闭合括号 } / ] 的位置,所以要删的逗号在上一行(Python 是例外,它直接指向逗号本身,见下表)。

把同一段输入实际跑过 5 个解析器,就能看出位置报告差异有多大(实测:scripts/benchmarks/json-trailing-comma/,2026-08-17,Node.js v26.7.0 / Python 3.14.6 / jq 1.7.1-apple / json5 2.2.3 / jsonc-parser 3.3.1)。输入是下面这个多行对象:

{
  "a": 1,
  "b": 2,
}
解析器对尾随逗号的处理
V8 (Node.js) JSON.parse不合法。Expected double-quoted property name in JSON at position 22 (line 4 column 1)
Python json.loads不合法。Illegal trailing comma before end of object: line 3 column 9 (char 20)
jq不合法。jq: parse error: Expected another key-value pair at line 4, column 1
JSON5合法(无错误)
jsonc-parser不合法。PropertyNameExpected at offset 22; ValueExpected at offset 22

位置指向方式因解析器而异。V8 和 jsonc-parser 指向闭合括号的位置(offset 22 / line 4 column 1),jq 指向括号所在行,只有 Python 直接指向逗号本身(line 3 column 9)。

看到报错信息但找不到那个逗号时,把文件粘贴到 JSON 格式化工具里,它会标出对应行。其他类型的解析报错与排查方法,见 JSON parse 报错排查

为什么 JSON 禁止尾随逗号

RFC 8259在新标签页中打开 中,逗号是值与值之间的分隔符(separator),不是每个值后面的终止符(terminator)。Section 2 的文法定义数组为"逗号分隔的值序列"、对象为"逗号分隔的成员序列"——不存在"最后一个值后面再放一个元素"的产生式规则。所以只跟着空白和闭合括号的逗号没有分隔的对象,符合规范的解析器必须拒绝它。

这个错误也正因为如此才常见:JavaScript 的对象字面量和数组字面量允许尾随逗号,很多编辑器格式化 .js 文件时会保留它。但 JSON.parse() 读的是严格 JSON,不是 JavaScript。在 .js 文件里完全正常的文本,一旦被当作 JSON 解析就会失败。把代码里的对象复制到 .json 文件,是尾随逗号混入的典型路径。完整的数据类型与嵌套结构规则,见 JSON 语法完全指南

自动移除尾随逗号

手动删一个逗号很快,但要批量处理文件或自动生成的 JSON 时需要自动化方案。

用序列化器生成,不要拼接字符串。JSON.stringify(以及各语言的等效功能)不会输出尾随逗号,从源头杜绝问题:

const data = { name: "Aoi", role: "Engineer" };
const json = JSON.stringify(data, null, 2);
// 永远合法 — 绝不会输出尾随逗号

保存时自动格式化。在 VS Code 里对 .json 文件执行 Format Document(或 Prettier 的 format-on-save),重新格式化时会顺带移除尾随逗号。这是保持手动编辑的配置文件干净的最简单方法。

正则表达式是最后手段。,\s*([}\]]) 匹配"逗号 + 空白 + 闭合括号":

const cleaned = source.replace(/,(\s*[}\]])/g, "$1");
const data = JSON.parse(cleaned);

把它当备用方案用。字符串值里可能包含逗号(比如 "a,}"),正则会误伤。只在你自己管理的文件上用,处理完后用 JSON 格式化工具 验证结果。

解析器选项只能"接受",不能"改写"。有些库可以容忍尾随逗号(比如 .NET 的 JsonSerializerOptions.AllowTrailingCommas)。这些选项让你的代码能读这个文件,但不会改变磁盘上的文件,也不会让另一个严格解析器接受它。如果 JSON 要发给其他服务,最终还是要删掉那个逗号。

用 Python 批量移除

标准库 json 不接受尾随逗号,但 json5 包可以按 JSON5 规范(允许尾随逗号)来解析。因为是走真正的解析器,不会像正则那样误改字符串值里的 ,}

# pip install json5
import json, json5

with open("broken.json") as f:
    data = json5.load(f)

with open("fixed.json", "w") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

用 Node.js 批量移除

用 npm 的 json5 包读入,再用标准 JSON.stringify 写出:

// npm install json5
import JSON5 from "json5";
import fs from "node:fs";

const data = JSON5.parse(fs.readFileSync("broken.json", "utf8"));
fs.writeFileSync("fixed.json", JSON.stringify(data, null, 2));

用 sed 批量处理多个文件

CI 流水线或 shell 脚本里要一次性清理很多文件时,sed 最方便。但它和上面的正则一样有误伤风险,处理后务必加一步解析验证:

sed -E 's/,[[:space:]]*([}\]])/\1/g' broken.json > fixed.json
python3 -c "import json; json.load(open('fixed.json'))"  # 验证

为什么 jq 修不了

jq 的解析器是严格的,包含尾随逗号的输入它直接拒绝。jq . broken.json 不会修复文件,而是报错停止。jq 是用来处理和查询合法 JSON 的工具,先用上面的方法之一把逗号删掉,再用 jq 做后续处理。

防止尾随逗号再次出现

修好一个文件不代表下一个不会再犯。有几个提前拦截的手段:

  • 编辑器:VS Code 会在 .json 文件里对尾随逗号显示警告(.jsonc 文件不会)。保持扩展名为 .json,警告才会一直开着
  • 知道高发场景:尾随逗号最常出现在手动编辑的配置文件、从 .js 源码复制出来的 JSON、用字符串拼接拼出来的 JSON 里。真正用序列化器生成的 JSON 是安全的

trailingComma 是从哪来的

保存时的自动格式化有时就是尾随逗号"复活"的原因。以下是 Prettier 官方文档和 issue tracker 中记录的内容:

项目内容来源
Prettier 默认值trailingComma 从 v3.0.0 起默认为 "all",之前是 "es5"prettier.io/docs/options在新标签页中打开
VS Code 扩展强制关闭 trailingComma 的是 Prettier VS Code 扩展本身,不是 Prettier 本体,且仅在解析器为 json 时生效 — 变更请求的 issue 已关闭且锁定prettier-vscode#589在新标签页中打开
tsconfig.json扩展名虽然是 .json,但 Prettier 本体会将其推断为 JSONC,保存时可能加上尾随逗号 — closed as not plannedprettier#15942在新标签页中打开
.jsonc 文件同样的 JSONC 推断也适用于所有 .jsonc 扩展名的文件 — issue 状态为 needs discussion,仍 openprettier#15956在新标签页中打开

在 CI 中加 JSON.parse 检查

JSON 感知的 linter 或构建流程中的 JSON.parse 步骤,能在尾随逗号到达下游服务之前拦截它。最小配置不需要任何依赖:

node -e "JSON.parse(require('fs').readFileSync(process.argv[1], 'utf8'))" config.json

把它做成 pre-commit hook,或在 CI 里遍历仓库所有 .json 文件跑一遍。手动编辑的配置文件尤其值得加这一步,因为尾随逗号最容易在那类文件里再次冒出来。

JSON5 和 JSONC 允许尾随逗号

如果你就是想在加行时保持 diff 干净而保留尾随逗号,有允许它的格式:

  • JSON5 是有正式规范的 JSON 超集,无条件允许尾随逗号、注释、无引号键、单引号。实测 5 个解析器中唯一 accepted: true 且零错误的(scripts/benchmarks/json-trailing-comma/
  • JSONC(VS Code 使用的"带注释 JSON")在 JSON 基础上加了注释。VS Code 使用的 jsonc-parser 实现是错误恢复(lenient recovery)模式:遇到尾随逗号不会抛异常、仍会返回值,但那个尾随逗号会被记录到 errors 数组中(见上表 jsonc-parser 行)。返回值和"规范上合法"是两回事,VS Code 配置文件"允许"尾随逗号指的是前者

注意适用范围。如果读这些文件的工具理解扩展语法,那就没问题;但 API 请求体、package.json、使用严格 JSON.parse 的服务,尾随逗号都是不合法的。

如果目标是"可读的严格 JSON",把结果过一遍 JSON 格式化工具确认无误即可。

常见问题

JSON 里能用尾随逗号吗?

不能。RFC 8259 把逗号定义为值与值之间的分隔符,不允许在最后一个值后面再放元素。所以闭合括号 } / ] 前面的逗号是不合法的,严格解析器会报 Unexpected token } 之类的错误拒绝解析。

怎么找到并删掉尾随逗号?

把 JSON 粘贴到 JSON 格式化工具。报错信息指向多余逗号后面那个闭合括号,删掉括号前面那行的逗号,再运行一次即可。要彻底避免,用 JSON.stringify 生成 JSON,不要手动拼字符串。

为什么 JavaScript 允许尾随逗号但 JSON 不允许?

JavaScript 的对象字面量和数组字面量出于语言便利性允许尾随逗号。JSON 是 JSON.parse 读取的严格数据格式,遵循 RFC 8259,没有"最后一个值后面放元素"的规则。同一段文本作为 JS 字面量合法、作为 JSON 不合法。

尾随逗号会报什么错?

最常见的是 V8/Node 的 Unexpected token }(或 ])、新版 V8 的 Expected double-quoted property name、Python 的 Expecting property name enclosed in double quotes。含义都一样:解析器在期待另一个值或键的位置遇到了闭合括号。

不删逗号、只让解析器容忍行不行?

有些解析器可以配置为容忍尾随逗号(比如 .NET 的 AllowTrailingCommas)。但那只是帮读文件的代码能跑通,不会让文件对另一个解析器合法,也不会让它适合传输。要互操作的 JSON,还是得删掉那个逗号。

JSON5 里尾随逗号能用吗?

能。JSON5 明确允许尾随逗号,同时支持注释和无引号键。适合本地配置文件,但不能用于需要严格 RFC 8259 JSON 的 API 数据。

总结

  • 尾随逗号是闭合括号 } / ] 前面那个多余的逗号,标准 JSON 禁止它
  • 报错形如 Unexpected token }Expecting property name enclosed in double quotes。报告的位置是括号,逗号在括号前一行
  • 最快的修复:把文件粘贴到 JSON 格式化工具,读行号,删逗号
  • JSON.stringify 生成、保存时自动格式化,可以从源头防止尾随逗号再次出现
  • JSON5 / JSONC 允许尾随逗号,但只在理解它们的工具里有效,API 请求体里不合法