调接口的时候,返回体常常是一整行:几百个字符挤在一起,嵌套对象和数组套了三层, 想看某个字段的值,得用眼睛在屏幕上从左扫到右。
「格式化」这个动作看起来只是加缩进,但它背后其实是把一串字符重新理解成树, 再按树的深度重新排版。理解这一点,很多奇怪的报错就说得通了。
解析器先做两件事
第一步是词法分析:把字符流切成一个个有意义的 token。
{"a":1} 会被切成 {、"a"、:、
1、} 五个 token。
第二步是语法分析:按 JSON 的语法规则把 token 拼成树。
遇到 就开一个对象节点,遇到 [ 就开一个数组节点,
遇到 就关闭当前对象。这棵树就是格式化要用的结构。
格式化本身反而简单:从根节点往下递归,每深一层就多两个空格(或者一个 Tab), 把每个键值对写到新的一行。所以「格式化」= 解析成树 + 按深度重排, 如果解析这一步失败,格式化根本没开始。
为什么错误信息总在奇怪的位置
因为解析器是边读边判断的。它在读到某个字符时才发现前面有问题, 报错位置通常是「发现问题的地方」,而不是「真正出错的地方」。
几个最常见的:
-
Unexpected token '}'—— 十有八九是对象最后一个键值对后面多了逗号。 解析器读完逗号,期待下一个键名,结果遇到},就在}的位置报错。 -
Unexpected token ''—— 用了单引号。 JSON 规范只认双引号,这一点和 JavaScript 的对象字面量不一样。 -
Unexpected end of JSON input—— 内容被截断了。 通常是复制的时候少复制了几个字符,或者接口返回本身就不完整。 -
Unexpected token /—— 出现了斜杠。JSON 不支持注释。
JSON 为什么不允许注释
这不是疏忽。JSON 的作者 Douglas Crockford 明确说过,加注释会让解析器变复杂, 而且有人会把注释当成配置项来用,最后配置文件变成「注释驱动的编程」。
现实是,很多人确实需要注释:VS Code 的 settings.json 就有注释,
TypeScript 的 tsconfig.json 也有。它们用的是 JSONC(JSON with Comments)——
一个非标准的变种,正式传输数据时仍然会去掉注释再发送。
所以如果你从某个配置文件里复制了一段带 // 的内容,粘进标准 JSON 解析器一定会报错。
这不是工具的问题,是格式的问题。
什么时候该压缩
格式化的代价是体积。一个 10 KB 的 JSON,格式化后可能变成 13~15 KB, 因为每个层级都插入了缩进和换行。
需要压缩的场景很具体:
- 塞进 URL 参数(空格和换行要额外编码)
- 写进环境变量或命令行参数
- 作为字符串常量嵌进代码
- 接口请求体,能省一点带宽
反过来,日志、配置、调试输出都该保持格式化状态,因为读的人比机器多。
一个小习惯
我给这个工具加了 Ctrl / ⌘ + Enter 直接格式化的快捷键。
原因很实际:粘贴完内容,手还在键盘上,不用去摸鼠标。
这类小动作一天重复几十次,省下来的是注意力。
另外,所有处理都在浏览器里完成。包含敏感字段的接口响应,可以放心粘进来—— 页面没有后端,断网也能用。