FormatArc JSON 格式化器中去除注释后的 JSON 格式化结果FormatArc JSON 格式化器中去除注释后的 JSON 格式化结果
作者: FormatArc 编辑部发布日期: 2026-09-02更新日期: 2026-09-02

JSON 可以注释吗?json注释语法与 4 种替代方案

JSON 可以注释吗?— 先说结论

不行。标准 JSON(RFC 8259)在任何位置都不允许注释。在 .json 文件里写 ///* ... */,严格解析器会直接报 "Unexpected token" 错误。这不是什么小限制,而是语法结构本身的约束。RFC 8259 第 2 节的语法定义中根本不存在接受注释的规则。但第 9 节明确写道:「JSON 解析器可以接受非 JSON 格式或扩展(MAY accept non-JSON forms or extensions)」——就这一句话,构成了 JSONC 和 JSON5 合法存在的基础。

如果你确实需要在 JSON 里留注释、临时禁用某个配置值、或者在字段旁边加说明,实际可用的方法有 4 种:

  • JSONC — VS Code 采用的「带注释的 JSON」
  • JSON5 — 包含注释、尾随逗号、宽松语法的正式 JSON 超集
  • 在标准 JSON 里放 "_comment": "..." 这样的占位字段
  • 解析前把注释去掉

下面逐一讲每种方法的适用场景,以及怎么把带注释的 JSON 转回标准 JSON。

只需要快速结论的话,按用途这样选:

  • 正在编辑 VS Code 或 Microsoft 系的配置文件,直接用 JSONC
  • 新项目选配置格式,用 JSON5 更省心
  • 解析器改不了,用 _comment 字段或注释去除来应对

带注释的 JSON 不需要先去掉注释再粘贴。直接贴进 FormatArc JSON 格式化器,解析报错旁边会出现「自动修复」按钮。点击后显示要应用的规则列表,确认后 ///* */ 就会被移除,得到干净的 JSON。所有处理都在浏览器内完成,数据不会离开你的设备。想让格式化后的结果更易读,可以参考 JSON 排版工具

JSON 为什么不支持注释

JSON 的设计者 Douglas Crockford 曾公开说明,注释是被刻意从规范中拿掉的。原因是注释里嵌入解析指令的情况确实发生过,导致不同解析器之间互操作性被破坏。结果是 JSON 变成了这样:

  • 小 — 语法一页能写完
  • 无歧义 — 每个值的解读方式唯一
  • 可移植 — 任何语言的内置解析器行为一致

代价是,你没法在 JSON 文件本身里留下「为什么设了这个值」的说明。这就是取舍,也是很多工具选择 JSONC 或 JSON5 这类超集的原因。如果想了解 JSON 本身的语法规则,可以参考 JSON 语法指南

ECMA-404 与 RFC 8259:都禁止注释吗

都禁止。JSON 有两个标准定义其语法——ECMA-404在新标签页中打开RFC 8259在新标签页中打开——两者的语法中都没有接受 ///* */ 的规则。但两者对「如何处理不符合标准的输入」采取了完全不同的方向。

各自标准定义的内容

ECMA-404(第 2 版,2017)RFC 8259(Internet Standard 90,2017)
发布机构Ecma InternationalIETF
规定范围仅语法。第 1 节声明其唯一目的是定义有效 JSON 文本的语法语法加上互操作性的语义约束
语法中是否包含注释不包含不包含
对不符合输入的处置第 2 节规定「符合规范的处理器不应接受不符合规范的 JSON 文本(should not accept)」第 9 节规定「JSON 解析器可以接受非 JSON 格式或扩展(MAY accept)」
与另一方的关系第 3 节声明两个规范旨在描述同一语法语言,并明确「RFC 8259 规定的语义约束对本规范不具有规范性」用不同的形式化方法规定相同的语法
RFC 2119 关键字记法不使用使用

JSONC 和 JSON5 不构成规范违规的依据,正是 RFC 8259 第 9 节的这一句话。反过来,只看 ECMA-404 实现的解析器,拒绝带注释的输入才是符合规范的行为。这就是为什么同样是「遵循标准」的解析器,行为会出现分歧。

各解析器实际抛出的错误信息

大多数解析器从不会说出「注释」这个词。它们在第一个意外的 / 处停下,报告它本来期望找到的 token 名称,这使得错误信息很难直接追溯到一条多余的注释。下表展示了当解析器读取下面的文件时,各常见解析器实际输出的错误信息:

{
  // server settings
  "host": "localhost",
  "port": 8080 /* default */
}
解析器实际输出的错误信息
JSON.parse(Node.js / V8,Chrome 和 Edge 同引擎)SyntaxError: Expected property name or '}' in JSON at position 4 (line 2 column 3)
JSON.parse,注释在值之前SyntaxError: Unexpected token '/', "{"port": /* default"... is not valid JSON
JSON.parse,注释在值之后SyntaxError: Expected ',' or '}' after property value in JSON at position 14 (line 1 column 15)
Python json.loadsjson.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
Python json.loads,注释在值之前json.decoder.JSONDecodeError: Expecting value: line 1 column 10 (char 9)
jqjq: parse error: Invalid numeric literal at line 2, column 5
VS Code(文件被当作严格 JSON 处理时)Comments are not permitted in JSON.

上表中除 VS Code 外,其余 6 行均是在本站用上述代码片段实际复现的结果。VS Code 那一行是编辑器语言服务在界面上显示的文案,无法通过命令行复现。这里有 3 点值得注意:

  • 只有 VS Code 直接点出了真正的问题。它的 JSON 语言服务会对每处注释标注「Comments are not permitted in JSON.」——但仅限于被当作严格 JSON 处理的文件。settings.jsontsconfig.json 里的同样注释会被当作 JSONC 解析而静默接受。
  • JSON.parsejson.loads 责怪的是下一个 token,而不是注释。「Expected property name」或「Expecting value」意味着解析器在 / 处停下了——行号和列号指向注释本身,但错误信息里从未提及注释。
  • jq/ 误读为数值。「Invalid numeric literal」看起来像是数据问题,但在那个行列位置,通常是一条注释。

如果你看到这些错误信息但文件里看不到注释,说明语法的其他位置出了问题。可以结合 JSON parse 报错排查 逐行定位原因。

方法 1: JSONC — 带注释的 JSON

JSONC 是 Microsoft 在 VS Code 中采用的非正式扩展,在标准 JSON 基础上增加了两种注释:

  • // 行注释(到行尾)
  • /* 多行注释 */

其他方面和标准 JSON 完全一样。典型的 JSONC 文件长这样:

{
  // VS Code 启动时使用的主题
  "workbench.colorTheme": "Default Dark Modern",

  /* 编辑器全局设置
     对所有语言生效 */
  "editor.tabSize": 2,
  "editor.formatOnSave": true
}

VS Code 的 settings.jsontsconfig.jsonlaunch.json,以及大部分 Microsoft 系工具都默认使用 JSONC。Deno 的配置文件(deno.json)也是。

解析 JSONC

JSONC 不能用内置的 JSON.parse 直接读,需要专用库。

Node.js:

// npm install jsonc-parser
import { parse } from "jsonc-parser";
const data = parse(sourceText);

Python:

# pip install jstyleson
import jstyleson
data = jstyleson.loads(source_text)

VS Code 本体自带 JSONC 解析器,所以 settings.json 里写注释不会出问题。

只想用行注释(//)时的最小配置

实际工作中,注释几乎只用到行注释 //。需要 /* */ 块注释的场景很少,如果只是想给配置留一行说明,下面的最小配置就够。

在 VS Code 里,不需要把整个文件切成 JSONC 模式,只要把当前文件的语言模式改成「JSON with Comments」,// 注释就不会再标红。点窗口右下角的语言标识(显示「JSON」),选「JSON with Comments」即可。

但改语言模式只是消掉编辑器里的报错提示。真正读这个文件的程序如果解析器不支持 JSONC,运行时的 "Unexpected token" 错误依然存在。如果你要把带注释的 .json 传给 JSON.parsejson.loads,要么先经过 JSONC 专用库解析,要么用后面介绍的注释去除方法转成标准 JSON 再传。

方法 2: JSON5 — 有正式规范的扩展

JSON5(json5.org在新标签页中打开)是拥有正式规范的 JSON 超集,从 ECMAScript 5 借来了几个实用特性:

  • 行注释和多行注释
  • 对象和数组的尾随逗号
  • 有效标识符的键可以省略引号
  • 单引号字符串
  • 行续接实现多行字符串
  • 十六进制数、省略前导/尾随小数点、Infinity / NaN

JSON5 文件的写法相当宽松:

{
  // 预发布环境的功能开关
  features: {
    newDashboard: true,
    legacyNotifications: false,
    rateLimitRps: 0xff,
  },
  welcomeMessage: 'Hello, world',
  /* 尾随逗号也允许 */
}

JSON5 有公开规范,所以几乎所有语言都有对应库。Node.js 用 json5在新标签页中打开,Python 用 pyjson5,Ruby 用 json5,都很常见。

JSONC 和 JSON5 该选哪个

看起来差不多,但特性不同:

JSONCJSON5
正式规范有(spec.json5.org在新标签页中打开
注释支持支持
尾随逗号部分支持支持
键省略引号不支持支持
单引号字符串不支持支持
生态Microsoft / VS Code独立,npm 等

选择标准:

  • 正在编辑 Microsoft / VS Code 配置文件 → 你已经在用 JSONC 了,继续就好
  • 新项目选配置格式 → 有规范文档可以指给工具的 JSON5 更省心
  • 和标准 JSON 解析器的兼容性是第一位 → 保持纯 JSON,用下面的应对模式

各实现的支持情况

下表对比了 5 种常见的「非标准」特性在严格标准和两个超集中的表现。RFC 8259 列反映的是 RFC 8259在新标签页中打开 第 2 节的语法(与 ECMA-404在新标签页中打开 的规定一致)。JSON5 列反映公开的 JSON5 规范在新标签页中打开,JSONC 列反映 VS Code 文档中描述的 Microsoft 非正式扩展。

特性RFC 8259 允许?JSONCJSON5
行注释 //不允许支持支持
块注释 /* */不允许支持支持
尾随逗号不允许可选支持
键省略引号不允许不支持支持
单引号字符串不允许不支持支持

RFC 8259 列全是不允许,原因是第 2 节的语法中没有接受这些特性的 production rule。字符串必须用双引号包裹,键必须是字符串,对象或数组最后一个值后面不能跟元素。JSON5 的规范明确加入了 ECMAScript 5 的语法,所以 5 种都支持。JSONC 始终加上两种注释,但保留严格 JSON 的双引号键和字符串。尾随逗号的支持因解析器而异(JSONC 规范只说解析器可以接受(MAY),参考实现 jsonc-parserallowTrailingComma 选项默认关闭),所以表里标的是「可选」而不是「支持」。

保持标准 JSON 的同时保留注释

如果第三方服务只接受标准 JSON,你可以不换解析器,改用字符串字段来留备注。

模式 1: _comment 字段

{
  "_comment": "在上游超时就增加重试次数",
  "retries": 3,
  "timeout_ms": 5000
}

下划线开头的键在消费端通常被忽略,大多数代码也能把它当普通数据处理。这是最简单的应对方式。

模式 2: 每个字段旁边放注释键

{
  "retries": 3,
  "retries_comment": "再大就会超过上游超时时间",
  "timeout_ms": 5000,
  "timeout_ms_comment": "和负载均衡器的超时时间对齐"
}

文件会冗长一些,但哪条注释对应哪个字段一目了然。

模式 3: 外层元数据块

{
  "$meta": {
    "generated_by": "deploy.sh",
    "purpose": "预发布环境的服务配置"
  },
  "service": {
    "port": 8080,
    "retries": 3
  }
}

在最外层放一个元数据专用对象,正文负载不用动,上下文就保留了。

三种模式都会把实际数据写进文件,严格解析器照样能读。缺点是多出来的字段成了 schema 的一部分,消费端也需要知道这些字段的用途。

在 package.json 里写注释

package.json 是 npm 读取的标准 JSON 文件,不能写 ///* */。写了的话 npm install 会在 JSON.parse 阶段直接失败。但 npm 会忽略不认识的最外层键,所以上面的应对模式可以直接套用。

最常用的方式是往约定的 "//" 键里写备注:

{
  "//": "使用私有 registry 的配置,仅内网 CI 生效",
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "build": "tsc -p ."
  }
}

同一个键在一个对象里只能出现一次,要留多条说明就用数组:

{
  "__comments": [
    "部署脚本不在这个文件里管理",
    "engines 要和 CI 的 Node 版本保持一致"
  ],
  "name": "my-app",
  "engines": { "node": ">=20" }
}

npm 本身会忽略这些键,但 npm publish 发布的包里备注也会一并带出去。适合内部工具或私有仓库的 package.json

.json 文件里用 // 键的注意点

"//" 键是社区约定,不是 JSON 规范的一部分。任何标准解析器都会把它当成一个普通的字符串键值对。也就是说:

  • 你的 API 客户端如果按 schema 严格校验,可能会把 "//" 当作未知字段拒绝或警告
  • 如果文件被 jqpython -m json.tool 格式化,"//" 键会被原样保留
  • 多个 "//" 键不能在同一个对象里重复,需要多条说明时用数组

如果这个 JSON 会被外部服务消费,最好先确认对方是否容忍未知键。不确定时,用 $meta 外层块比散落多个 "//" 键更清晰。

如果想把配置意图留得更清楚,用后面介绍的注释去除模式,先按 JSONC 写再转成发布用标准 JSON 更稳妥。

去除注释后交给标准解析器

如果你手上是 JSONC 或 JSON5 文件,但需要交给标准 JSON 解析器,有两条路:用 JSONC/JSON5 库解析后再序列化为 JSON,或者用正则表达式去掉注释。

Node.js 用 json5 包的示例:

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

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

最小正则也能去掉注释。但字符串字面量里包含 // 的话会被误切,不是你自己管理的文件就别用。

const stripped = source
  .replace(/\/\/[^\n\r]*/g, "")
  .replace(/\/\*[\s\S]*?\*\//g, "");
const data = JSON.parse(stripped);

稳妥的做法始终是走专用解析器。

批量处理时的注意事项

项目中如果有多个 JSONC 配置文件需要统一转为标准 JSON,建议写一个小的转换脚本,统一用 jsonc-parserjson5 库解析后输出。正则表达式方案在单文件、内容可控时够用,但批量处理时风险急剧上升——任何一个字符串里出现 ///* 都会导致数据损坏。

在 Python 中处理 JSONC / JSON5

Python 标准库 json 只能读严格 JSON,JSONC 或 JSON5 直接传给 json.loads 会在注释行报错。应对方法有两种。

想轻量处理的话,用标准库 re 去掉注释再 json.loads

import json, re

def load_jsonc(text):
    text = re.sub(r"//[^\n]*", "", text)        # 行注释
    text = re.sub(r"/\*.*?\*/", "", text, flags=re.S)  # 块注释
    return json.loads(text)

with open("tsconfig.json", encoding="utf-8") as f:
    config = load_jsonc(f.read())

这个正则会连字符串字面量里的 // 也切掉,不是自己管的文件别用。

要正确读取尾随逗号、省略引号等特性,用专用库。JSONC 用 jstyleson,JSON5 用 json5pyjson5

# pip install jstyleson json5
import jstyleson
import json5

config = jstyleson.load(open("settings.json", encoding="utf-8"))   # JSONC
data = json5.load(open("config.json5", encoding="utf-8"))          # JSON5

只读配置的话正则够用,但输入不可信、或者可能混有尾随逗号和单引号的情况,专用库更稳。

如果你的项目同时依赖多个 JSON 文件且其中一部分是 JSONC(例如从 CI 流水线自动生成的配置),建议统一在入口处用 jstylesonjson5 解析,避免散落在各处的 re.sub 正则不一致。

用 FormatArc 整理并检查结果

转成标准 JSON 之后,贴进 FormatArc JSON 格式化器 查看格式化结果。如果解析器还在报错(典型的如 Unexpected token /),大概率是注释还没清干净。

FormatArc 本身使用浏览器内置的 JSON.parse,但解析失败时可以走自动修复。步骤:

  1. 带注释的 JSON 直接贴进 JSON 格式化器
  2. 点报错旁边的「自动修复」
  3. 确认要应用的规则列表,点「应用」
  4. 查看、验证、复制格式化后的 JSON

自动修复处理 4 种:// 行注释、/* */ 块注释、尾随逗号、连续逗号。字符串里的 //(比如 "https://example.com")不在处理范围内,URL 不会被破坏。JSON5 的单引号或无引号键不在自动修复范围内,这种情况先用 JSON5 库解析再贴进来。所有处理在浏览器内完成,数据不离开你的设备。

FormatArc JSON 格式化器中去除注释后的 JSON 格式化结果FormatArc JSON 格式化器中去除注释后的 JSON 格式化结果

常见问题

RFC 8259 对 JSON 注释是怎么规定的?

RFC 8259 从头到尾没有出现过「comment」这个词。第 2 节的 JSON 语法(ABNF)定义了两个 token 之间能出现的空白只有 4 种:space / tab / line feed / carriage returnws = *( %x20 / %x09 / %x0A / %x0D )),不存在接受 ///* */ 的 production rule,所以严格解析器会报 "Unexpected token" 错误。第 9 节则明确写「JSON 解析器可以接受非 JSON 格式或扩展(MAY)」,这是 JSONC 和 JSON5 不构成规范违规的依据。

.json 文件里能写 ///* 注释吗?

不能(如果这个文件会被严格解析器如 JSON.parsejson.loadsencoding/json 读取)。第一个注释处就会报 "Unexpected token"。把扩展名改成 .jsonc 并用 JSONC 支持的读取器,或者迁移到 JSON5。

能只注释掉 .json 文件里的一行吗?

不能。JSON 里根本没有行注释语法,想在某行前加 // 来临时禁用一个值,那行本身就是语法错误。想临时禁用一行的写法有 3 种:直接删掉那个键、靠版本管理的历史记录找回;把要禁用的键改名为带 _disabled_ 前缀的键来搁置;把文件切到支持 JSONC 的环境里正式注释。三选一。

VS Code 为什么在 settings.json 里写注释不会报错?

因为 VS Code 把 settings.json 这类文件当作 JSONC 而不是严格 JSON 来处理。内置解析器接受 ///* */。其他用 JSON.parse 读同一个文件的编辑器,如果不理解 JSONC,就会报错。

JSON5 是标准吗?

JSON5 在 spec.json5.org在新标签页中打开 有公开规范,但不是 IETF 或 ECMA 的正式标准。在开发工具生态中支持很广泛,但不能替代 API 或通信协议中使用的 RFC 8259 JSON。

FormatArc 支持 JSONC 或 JSON5 吗?

JSONC 可以通过自动修复处理。带注释的 JSON 直接贴进去,走「自动修复」到「应用」,///* */ 就会被移除,尾随逗号和连续逗号也一并修正。JSON5 的单引号或无引号键不在自动修复范围内,这种情况先用 JSON5 库解析再贴进来。

如果一定要注释,是不是得用 YAML?

YAML 用 # 原生支持注释。如果主要目的就是加注释、且格式可以换,YAML 对配置文件来说往往是更合适的选择。YAML 和 JSON 的语法差异与选型,见 YAML 和 JSON 的区别。FormatArc 提供 YAML 和 JSON 之间的互转工具。

TOML 呢?

TOML 也用 # 写注释,且从设计之初就面向配置文件场景,key 不需要引号就能保持可读性。如果你的文件主要是人工编辑、而不是服务间传递数据,TOML 比 JSON 更合适。但如果需要在多个服务之间做数据交换,TOML 解析器的普及程度远不如 JSON,此时还是用 JSON 配合注释去除更稳妥。

总结

  • 标准 JSON 不支持注释,这是规范刻意的约束
  • JSONC 允许 ///* */,VS Code 生态广泛使用
  • JSON5 是有规范的超集,支持注释、尾随逗号、宽松语法
  • 解析器改不了的话,用 _comment 字段或外层元数据块应对
  • 带注释的 JSON 直接贴进 JSON 格式化器,用自动修复去掉注释和尾随逗号后即可整理验证