如何格式化、校验、压缩和查看 JSON
用 JavaScript、Python、jq、Prettier、VS Code 或浏览器本地工具格式化并校验 JSON;然后在压缩文本、美化输出和树形视图之间做选择,同时不悄悄改动数据。
先给结论: 如果文本已经是合法 JSON,那就解析它、再带缩进重新输出。JavaScript 里用 JSON.stringify(JSON.parse(raw), null, 2),Python 里用 json.dumps(json.loads(raw), indent=2),命令行用 jq . input.json 或 python3 -m json.tool input.json。如果输入里有尾随逗号、单引号、注释或没加引号的键,先用 JSON Fix 修复或校验。
格式化 JSON 不会改变值。它要解决的是:让同一个对象变得足够好读,好让人能复核它、diff 它、贴进 bug 报告,或者提交进仓库 —— 而不用眯着眼睛盯一条长长的单行。
格式化 JSON 到底做了什么
JSON 格式化器解析一个 JSON 值,然后用可预期的空白把它重新序列化:
- 每个对象成员单独占一行。
- 嵌套的对象和数组带缩进。
- 字符串保留双引号。
- 逗号只出现在值之间,绝不跟在最后一个值后面。
- 不会引入注释、单引号或 JavaScript 专有的值。
格式化前:
{"user":{"id":"u_123","name":"Ada","roles":["admin","editor"],"active":true}}
用 2 个空格格式化后:
{
"user": {
"id": "u_123",
"name": "Ada",
"roles": [
"admin",
"editor"
],
"active": true
}
}
这两份文档在 JSON 里描述的是同一个值。JSON token 之间的空白是无意义的,所以缩进和换行对解析器来说不该有任何影响。
"不该"这两个字用得很讲究。好的格式化器会保住 JSON 的值;但只要你喂给它重复的键、超大的数字,或者非 JSON 的 JavaScript 值,解析加序列化这套组合仍然会制造边界情况。下面几节会专门讲这些。
挑对格式化方式
| 场景 | 用什么 | 为什么 |
|---|---|---|
| 浏览器里快速清理 | JSON Fix | 先修常见的损坏 JSON,再在本地格式化 |
| 代码里的 JavaScript 值 | JSON.stringify(value, null, 2) |
每个 JS 运行时都内置 |
| JavaScript 里的 JSON 文本字符串 | JSON.stringify(JSON.parse(raw), null, 2) |
格式化之前先校验 |
| Python 脚本或 notebook | json.dumps(data, indent=2) |
Python 内置 |
| Shell 管道或 API 响应 | jq . |
快、可脚本化、报错清楚 |
| 仓库里的机器可读文件 | Prettier | 在 CI 里保持风格一致 |
tsconfig.json 或 VS Code 配置 |
VS Code / Prettier JSONC | 能处理 JSONC 的注释和尾随逗号 |
调试 API 响应时,请用那种遇到坏 JSON 会大声报错的格式化器。
在 JavaScript 里格式化 JSON
对一个 JavaScript 值来说,格式化器就是 JSON.stringify,第三个参数控制缩进:
const value = {
user: {
id: 'u_123',
name: 'Ada',
roles: ['admin', 'editor'],
active: true
}
};
const pretty = JSON.stringify(value, null, 2);
console.log(pretty);
输出:
{
"user": {
"id": "u_123",
"name": "Ada",
"roles": [
"admin",
"editor"
],
"active": true
}
}
要四个空格就传 4,要制表符就传 '\t':
JSON.stringify(value, null, 4);
JSON.stringify(value, null, '\t');
有个细节容易被忽略:space 参数是有上限的。传 100 并不会得到 100 个空格的缩进 —— JavaScript 把数字缩进封顶在 10 个空格。
格式化一个 JSON 字符串
如果你手上是文本,先解析:
const raw = '{"name":"Ada","active":true}';
const formatted = JSON.stringify(JSON.parse(raw), null, 2);
console.log(formatted);
这比用字符串替换硬塞换行要好得多。JSON 是嵌套语法:字符串里的逗号和数组元素之间的逗号根本不是一回事,靠正则做格式化,早晚会在真实输入上翻车。
用 Node.js 格式化 JSON 文件
写脚本时,把文件读成文本、解析、再写回去,末尾补一个换行,好让 git diff 保持干净:
import { readFile, writeFile } from 'node:fs/promises';
const input = await readFile('input.json', 'utf8');
const value = JSON.parse(input);
const output = `${JSON.stringify(value, null, 2)}\n`;
await writeFile('output.json', output);
如果脚本会覆盖文件、而输入又很重要,那就先写到临时文件 —— 这样解析一旦失败,你还能中止操作。
在 JavaScript 里递归排序键
排序键对稳定的 diff、快照和生成的测试数据很有用。但它不该给数组排序,因为在 JSON 里数组顺序是有意义的。
function sortJsonKeys(value) {
if (Array.isArray(value)) {
return value.map(sortJsonKeys);
}
if (value && typeof value === 'object' && value.constructor === Object) {
return Object.keys(value)
.sort((a, b) => a.localeCompare(b))
.reduce((result, key) => {
result[key] = sortJsonKeys(value[key]);
return result;
}, {});
}
return value;
}
const formatted = JSON.stringify(sortJsonKeys(value), null, 2);
能不排就别排。对人工维护的配置文件来说,保留作者的分组方式,往往比按字母排序更好读。
在 Python 里格式化 JSON
Python 内置的 json 模块流程一样:先 load,再带缩进 dump。
import json
raw = '{"name":"Ada","active":true}'
data = json.loads(raw)
print(json.dumps(data, indent=2))
格式化文件:
import json
with open("input.json", encoding="utf-8") as f:
data = json.load(f)
with open("output.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
f.write("\n")
排序键:
json.dumps(data, indent=2, sort_keys=True)
如果 JSON 里含有超大的整数 ID,用 Python 格式化通常更稳妥,因为 Python 的整数是任意精度的。JavaScript 把 JSON 数字解析成 Number,无法精确表示每一个 64 位整数。要是你的 JSON 里有 9223372036854775807 这样的 ID,请把它们保留成字符串,或者换一个专门保留大数的解析器。
在命令行里格式化 JSON
jq
用恒等过滤器时,jq 默认就会美化输出:
jq . input.json
存到另一个文件:
jq . input.json > output.json
格式化 curl 的响应:
curl -s https://api.example.com/users | jq .
排序键:
jq --sort-keys . input.json
改成压缩而不是格式化:
jq -c . input.json
要避开这个经典错误:
jq . input.json > input.json
shell 会在 jq 读之前就以写模式打开 input.json,结果就是把文件清空。用临时文件:
tmp="$(mktemp)"
jq . input.json > "$tmp" && mv "$tmp" input.json
不装 jq,用 Python
只要装了 Python,基础的格式化用 json.tool 就够:
python3 -m json.tool input.json
从标准输入读:
printf '%s\n' '{"name":"Ada","active":true}' | python3 -m json.tool
排序键:
python3 -m json.tool --sort-keys input.json
用四个空格:
python3 -m json.tool --indent 4 input.json
在 VS Code 和 Prettier 里格式化 JSON
VS Code 不装扩展就能格式化 .json 文件:打开文件,在命令面板里执行 Format Document,或者用编辑器快捷键。处理单个文件够用了。
面向整个仓库,请用 Prettier,这样格式化才可复现:
npm i -D prettier
npx prettier --write "**/*.{json,jsonc}"
npx prettier --check "**/*.{json,jsonc}"
一份小配置通常就够:
{
"tabWidth": 2,
"trailingComma": "none"
}
json 和 jsonc 要分清楚:
.json应该是严格 JSON:没有注释,没有尾随逗号。.jsonc在支持 JSONC 的工具里允许注释和尾随逗号。tsconfig.json和 VS Code 的settings.json虽然扩展名是.json,编辑器通常按 JSONC 对待。- API、包元数据、锁文件和数据源基本都要求严格 JSON。
别以为编辑器格式化过就万事大吉了 —— 只要这个文件会被服务端、API、数据库或构建工具读取,就得确认它是严格 JSON。
什么时候格式化会改变你看到的内容
对合法 JSON 来说,格式化本应保住值。风险来自"解析再序列化"这套行为:
| 情况 | 可能发生什么 | 更稳妥的做法 |
|---|---|---|
| 重复的对象键 | 很多解析器只保留最后一个值 | 在数据约定里就把重复键视为非法 |
| 超大数字 | JavaScript 可能把超过 Number.MAX_SAFE_INTEGER 的整数四舍五入 |
给大 ID 加引号,或换用支持大数的解析器 |
JS 里的 NaN 或 Infinity |
在数组和对象值里会被序列化成 null |
输出 JSON 之前明确地转换它们 |
undefined、函数、Symbol |
这些对象属性会被直接省略 | 换成明确的 JSON 值 |
Date 对象 |
会变成 ISO 字符串 | 先确认 API 要的是字符串还是时间戳 |
BigInt |
JSON.stringify 会抛异常 |
格式化前先转成字符串 |
调试时这个区别很重要:格式化一份 JSON 文本文件是一回事,序列化一个活的 JavaScript 对象是另一回事。
为什么你的 JSON 格式化不了
格式化器只能格式化合法 JSON。解析失败,它就没有可缩进的结构。
常见原因:
}或]前面有尾随逗号- 用单引号包的字符串
- 没加引号的对象键
//或/* */注释- 从 Python 来的
True、False、None - 从 JavaScript 来的
undefined、NaN、Infinity - 复制响应时,JSON 前后带上了多余的日志文本
- API 响应被截断,缺了闭合的大括号或方括号
要做严格语法检查,用 JSON 校验器。日志、配置片段或大模型输出里的"近似 JSON",先用 JSON Fix 修,再格式化。下一节会讲为什么光靠解析成功还不够。
格式化之前先校验语法
格式化、压缩和查看,起点都是解析输入。而解析成功只说明这段文本在语法上是合法 JSON,它不检查 API 载荷里必填字段在不在、类型对不对。
把它拆成三个独立的问题:
| 层次 | 问题 | 常用工具 |
|---|---|---|
| 语法 | 这是合法的 JSON 文本吗? | JSON.parse、python -m json.tool、jq empty |
| 结构 | 必需的属性和类型都在吗? | JSON Schema、Ajv、Pydantic、Zod |
| 业务规则 | 这个值在当前操作里被允许吗? | 应用代码和领域检查 |
JavaScript 的语法检查:
function validateJsonSyntax(text) {
try {
return { valid: true, value: JSON.parse(text) };
} catch (error) {
return { valid: false, error: error.message };
}
}
命令行检查(输入非法时返回非零退出码):
jq empty input.json
python3 -m json.tool input.json > /dev/null
对 API 响应来说,解析之前还要检查 HTTP 状态码和 content-type。一个排版精美的登录页,它仍然是 HTML,不是 JSON。关于用 JSON Schema 做结构校验,见什么是 JSON?。
在线格式化 JSON,但不上传你的载荷
本站的 JSON Fix 工具把核心的修复、校验、格式化、压缩、排序和复制流程都放在你的浏览器里运行。格式化器用的模型和本地脚本没什么两样:解析值,可选地对对象键排序,然后以 2 或 4 个空格缩进输出 JSON。
这样用它:
- 把最小的、脱敏过的样本粘进输入编辑器。
- 选 2 个还是 4 个空格。
- 只有当稳定的对象顺序确实有帮助时,才打开 Sort keys。
- 损坏的 JSON 点 Repair & Format,严格 JSON 点 Validate。
- 把修复后的值用进 API 请求或配置文件之前,先复核一遍。
本地格式化降低了暴露面,但粘贴进来的 bearer token、API key、客户记录或私密配置仍然是敏感信息。放进任何网页、截图、聊天、issue 或 PR 之前,请先脱敏。更完整的隐私流程见在线修复 JSON。
先把数据转成 JSON,再格式化
有些人搜"format to JSON",其实想问的是"怎么把另一种数据形态转成 JSON"。那是另一个步骤。
YAML 转格式化的 JSON:
import json
import yaml
with open("config.yaml", encoding="utf-8") as f:
data = yaml.safe_load(f)
print(json.dumps(data, indent=2))
CSV 转格式化的 JSON:
import csv
import json
with open("users.csv", newline="", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
print(json.dumps(rows, indent=2))
转换时留意类型。CSV 没有原生的布尔、null、数字、对象或数组类型。邮政编码、商品编码、账号 ID 和大数字 ID 通常必须保持字符串,哪怕它们长得像数字。
更完整的转换流程,见 YAML 转 JSON 或 把 CSV、XML、YAML 转成 JSON。
为传输压缩 JSON
压缩是解析一个 JSON 值,再输出成不含无意义空白的形式。它是美化的反向操作 —— 既不是压缩算法,也不是加密。
const minified = JSON.stringify(JSON.parse(raw));
minified = json.dumps(json.loads(raw), separators=(",", ":"))
jq -c . input.json
内嵌的测试数据、需要复制的请求体,或者要求每行一条记录的系统,用压缩后的 JSON。可读的源文件请保持格式化状态 —— 除非这个仓库有意存放生成的压缩产物。
一般来说,HTTP 的 gzip 或 Brotli 省下来的比单纯删空白多得多,因为它会压缩重复的属性名和值。网络性能靠传输压缩,压缩 JSON 则用在"只想要紧凑源文本"或"需要按行分帧"的时候。前面关于重复键和大数字的提醒,对走普通 JavaScript 解析器的压缩同样适用。
嵌套很深的载荷用树形视图
如果你要的是可复制的文本、精确的标点或一份 git diff,格式化器最合适。而当你需要在庞大的嵌套载荷里逐层下钻、又不想滚过几千行时,树形查看器就好用了。
| 任务 | 最合适的视图 |
|---|---|
| 编辑或复制 JSON 文本 | 格式化器 / 编辑器 |
| 确认语法 | 校验器 |
| 展开大响应里的某一个分支 | 树形查看器 |
| 比较两份载荷 | 语义化 JSON diff |
| 抢救近似 JSON | 修复工具,之后再校验 |
在树里,先看容器类型再看值:{} 是对象,[] 是数组,数组下标是路径的一部分。显示在 users[2].profile.email 的字段,和 users.profile.email 完全不是一回事。空数组、空对象、null、缺失的属性、数字 0 和空字符串,在视觉上应该始终能区分开。
大文件要节制着看:把无关分支折叠起来,搜一个已知的键,先看一条有代表性的记录,别一上来就全展开。树形视图不会把非法 JSON 变合法 —— 先把文本修好,再去看解析结果。
JSON 查看器、JSON 校验器和 JSON Diff 都在浏览器里运行,各自负责同一套流程里的不同步骤。
一套实用的格式化流程
一次性调试:
- 把原始 JSON 格式化出来,先看清结构。
- 检查你真正关心的那个字段。
- 只有当目标端需要单行 JSON 时,才再压缩回去。
代码评审:
- 校验严格 JSON。
- 应用仓库自己的格式化器。
- 除非项目本来就用排序输出,否则别开 sort keys。
- 只提交格式化后的数据文件,别捎上无关的生成文件。
生产配置:
- 校验语法。
- 校验 schema 或必填字段。
- 检查大 ID 和可空字段。
- 原地重写文件之前先留个备份。
格式化让 JSON 更好读,但它证明不了这份载荷对你的应用是正确的。
格式化问题排查
| 症状 | 可能原因 | 怎么修 |
|---|---|---|
| 格式化器报 "Unexpected token" | 输入不是严格 JSON | 先看行列号,再修语法 |
| 输出的键顺序变了 | 开了 sort keys,或序列化器重排了对象键 | 人工分组重要的话就关掉排序 |
| 大 ID 变了 | JavaScript 数字精度丢失 | 把 ID 存成字符串,或换用能保留精度的解析器 |
| 注释不见了 | 你是按 JSON 而不是 JSONC 格式化的 | 注释只保留在 JSONC 文件里 |
| 执行完命令文件空了 | 输出重定向到了同一个输入文件 | 先写临时文件,再 mv |
| API 拒绝了格式化后的 JSON | 语法过了,但 schema 或业务规则没过 | 校验必填字段、类型、枚举和 null |
常见问题
在 JavaScript 里怎么格式化 JSON?
对 JavaScript 值用 JSON.stringify(value, null, 2)。如果手上是 JSON 字符串,先解析:JSON.stringify(JSON.parse(raw), null, 2)。先解析能在格式化之前确认这段文本确实是合法 JSON。
什么都不安装,怎么格式化 JSON 文件?
用 Python 自带的格式化器:python3 -m json.tool input.json。它会读文件、校验 JSON 并打印格式化结果。想让对象键按字母排序,加上 --sort-keys。
格式化 JSON 会改动数据吗?
缩进和换行不会改动 JSON 数据。但"解析再序列化"的工具会暴露一些边界情况:重复的键可能被合并成一个值,JavaScript 可能对超大数字做四舍五入,而 undefined 这类非 JSON 的 JavaScript 值根本无法表示。
为什么我的 JSON 格式化不了?
输入多半不是严格 JSON。常见原因有尾随逗号、单引号、没加引号的键、注释、Python 的 True 这类字面量、JavaScript 的 undefined,或者响应被截断了。先把语法修好或校验一遍。
JSON 用 2 个还是 4 个空格?
JavaScript 和 Web 项目里 2 个空格更常见,某些 Python 和 Java 团队习惯 4 个。缩进宽度属于无意义空白,所以保持一致比选几个空格重要得多。
该不该给 JSON 的键排序?
想要稳定的 diff、生成的测试数据或确定性的快照,就排序。如果现有顺序对人有意义(比如手工维护的配置里那些设置分组),就别排。JSON 数组的顺序是有意义的,所以格式化器不应该给数组排序。
能格式化带注释的 JSON 吗?
严格 JSON 不允许注释。部分编辑器和配置文件用的是 JSONC,它允许注释和尾随逗号,但期待 RFC 风格 JSON 的 API 和解析器会拒绝。JSONC 就按 JSONC 格式化;数据发给 API 之前,先按严格 JSON 校验。
在线格式化 JSON 安全吗?
取决于格式化在哪里运行。JSON Fix 工具把大部分修复和格式化工作放在你的浏览器里做,但把敏感值粘进任何网页、截图、issue 或聊天之前,先脱敏仍然是好习惯。
美化打印和格式化 JSON 是两回事吗?
在常规的 JSON 工具链里,这是同一个操作:解析一个值,带着缩进和换行重新序列化。有些工具把整个编辑器流程叫作"format",但并不存在另一套"JSON 美化打印语法"。
压缩 JSON 算压缩吗?
Minify 去掉的是可选空白。gzip、Brotli 这类压缩会对重复文本做编码,通常能把传输体积再降一大截。两者可以叠加,但真正关键的网络优化是 HTTP 压缩。
什么时候该用 JSON 树形查看器而不是格式化器?
浏览庞大的嵌套载荷用树;需要看到精确文本、编辑、复制或做按行 diff 时用格式化器。两者都需要先有合法 JSON,才能可靠地展示结构。
相关 JSON 工具与指南
- JSON Fix —— 在浏览器本地修复并格式化损坏的 JSON。
- JSON 校验器 —— 检查严格 JSON 语法及出错的行列位置。
- JSON 查看器 —— 用可折叠的树查看大型 JSON。
- 什么是 JSON? —— 语法、类型、示例与 JSON Schema。
- 在线修复 JSON —— 格式化之前先修好非法输入。
- 比较两份 JSON 文件 —— 归一化之后用 jq 或语义化 diff。
参考资料
- RFC 8259 —— JSON 数据交换格式。
- MDN: JSON.stringify —— JavaScript 的序列化与缩进行为。
- Python json 模块 ——
json.dumps、json.dump和json.tool。 - jq 手册 —— 命令行 JSON 格式化与过滤器。
- Prettier 文档 —— 仓库级的 JSON 与 JSONC 格式化。
最后校订于 2026 年 8 月。