使用方法
- 把要压缩的 JSON 粘进左侧「输入 JSON 文本」。页面打开时已经放了一段带两空格缩进的订单服务配置(171 字符),可直接点「压缩」看效果。
- 点「压缩」或按 Ctrl / Cmd + Enter。这是多行输入框,单独按 Enter 只换行不触发。
- 右侧「压缩结果」立刻显示单行最小形式,同时上方五张卡片给出压缩率、原字符数、压缩后字符数和两边的 UTF-8 字节数。
- 确认无误后点「复制结果」贴到别处,或点「下载 JSON」存成
.json文件(不带 BOM,可直接被后端JSON.parse读)。JSON压缩工具跑完一趟后还可以对结果再压一次,用于确认已经压到最小。 - 想还原成带缩进的可读版,请改用文末的格式化工具;本页只负责压缩方向。
这个JSON压缩工具能解决什么问题
接口返回、日志导出、配置下发这几条链路上的 JSON 通常带着两空格或四空格缩进,体积里塞的全是对解析毫无意义的空白。JSON压缩工具解决四件事:一是传输瘦身,示例里 171 字符的格式化配置压到 117 字符,省下 54 个字符、压缩率 31.6%,UTF-8 字节从 195 降到 141;二是统一出参,同一份数据无论写成两空格、四空格还是 Tab 缩进,压缩后得到的是逐字节相同的字符串,可以直接拿来做内容哈希或缓存键;三是找出冗余来源,对照表列出哪些写法在压缩过程中被改写,让你在源头就避免写出又长又易错的键名;四是暴露精度陷阱,12345678901234567890 会被解析成 12345678901234567000,压缩过程静默改了数值而没有任何警告。
本页只做压缩与体积统计。缩进美化、语法是否合法、键排序、两个 JSON 的差异对比,都不在这里做,请走文末分流。
原理和变量:为什么是 parse 再 stringify
核心只有一句:JSON.stringify(JSON.parse(输入))。两个参数都不传,走 ECMA-262 里 JSON.stringify(value) 的默认形式。
为什么不用正则删空白。正则分不清「语法空白」和「字符串里的空格」。对 {"s":" 空格 "} 做 replace(/\s+/g,'') 会把值里的两个空格一起删掉,输出 {"s":"空格"}——数据被改了,而且改得没有任何提示。走 parse 之后,语法空白在解析阶段就被丢弃,字符串值被完整保存在对象里,stringify 只负责按标准重新输出,值一个字符都不少。
第二个参数为什么必须空着。JSON.stringify 的第二参是 replacer,传 undefined 或不传都表示「保留全部键」。但如果误传一个数组,比如 JSON.stringify(o, ['a']),实测 {"a":1,"b":{"c":2}} 会变成 {"a":1},b 被整个丢掉;如果传函数 function (k, v) { return k === 'b' ? undefined : v },结果同样是 {"a":1}。这两处是真实的数据丢失,不是显示问题。
第三个参数为什么不给。第三参是缩进。实测传 null, 0 和不传等价;传 null, 2 就变回带两空格的格式化文本;传 null, 11 会被规范截到 10 个空格;传 null, -1 等同于 0;传字符串 ' ' 则用空格本身填充。压缩场景下唯一正确的选择就是不传。
字符数与字节数的区别。统计用两组口径:字符数取 String.length,按 UTF-16 码元计;字节数用 TextEncoder.encode() 的 byteLength。示例原文 171 字符但占 195 字节,差 24 字节来自「订单服务」等 8 个汉字——每个汉字在 UTF-8 里占 3 字节而只算 1 个字符。真正决定网络流量的是字节数,所以两个数都给你。
遵循的规范。JSON 语法由 ECMA-404 定义,交换格式由 RFC 8259 定义。本页不做任何超出这两份文档的宽松处理:尾逗号、单引号、注释、未加引号的键名一律报错,而不是猜测作者意图。
完整示例(数值仅作演示)
打开页面时输入框里是这段用两空格缩进的订单服务配置,JSON压缩工具输出的最小形式是:
{"name":"订单服务","version":"2.1.0","features":["限流","熔断","灰度发布"],"limits":{"qps":1200,"timeoutMs":3000},"enabled":true}
五张卡片分别是:压缩率 31.6%、原字符数 171、压缩后字符数 117、原 UTF-8 字节 195、压缩后字节 141。
把同一份数据改写成四空格缩进或 Tab 缩进(138 字符),压缩结果与上面逐字节相同;对已经压好的文本再压一遍,省下 0 个字符。这就是幂等性:压缩两次等于压缩一次,可以放心放在构建流程里反复跑。
体积构成上,示例里 features 这个键连值加引号共 31 字符,limits 子对象共 40 字符,而 enabled 只占 16 字符——长数组和嵌套对象才是压缩后的大头,缩进省下来的反而是零头。
输入范围与对照表
压缩过程会改写以下写法(前 12 行默认显示,点「加载更多改写规则」展开余下 2 行)。这一列是本页最该记住的部分:压缩不是纯删空白,有些值会被规范化。
| 原始写法 | 压缩后 | 发生了什么 |
|---|---|---|
| { "n" : 1.50 } | {"n":1.5} | 小数末尾补零被去掉 |
| { "n" : 1.0 } | {"n":1} | 整数值的 .0 被去掉 |
| { "n" : 1e3 } | {"n":1000} | 科学计数法展开成整数 |
| { "n" : -0 } | {"n":0} | 负零归零 |
| { "s" : "a\/b" } | {"s":"a/b"} | 斜杠不必转义 |
| { "s" : "\u4e2d\u6587" } | {"s":"中文"} | Unicode 转义还原成汉字 |
| {"\u4e2d":"x"} | {"中":"x"} | 键名同样被还原 |
| { "b":2, "10":1, "1":2, "a":3 } | {"1":2,"10":1,"b":2,"a":3} | 整数型键提前并按数值升序 |
| { "n" : 12345678901234567890 } | {"n":12345678901234567000} | 超出安全整数,末位被改 |
| { "n" : 1e400 } | {"n":null} | 溢出成 Infinity,JSON 无此值故写 null |
| { "s" : " 空格 " } | {"s":" 空格 "} | 值内空格原样保留 |
| { "s" : "line1\nline2" } | {"s":"line1\nline2"} | 值内换行仍是转义符,不折行 |
| { "n" : 1.7976931348623157e308 } | {"n":1.7976931348623157e+308} | 双精度最大值保留,指数补正为 e+308 |
| { "s" : "\u0009" } | {"s":"\t"} | 控制字符用短转义表示 |
不同排版风格能省下多少,同一份 {"a":1,"b":2,"c":[1,2,3]} 为例:
| 原始排版 | 原字符数 | 压缩后 | 省下 |
|---|---|---|---|
| 已是最小形式 | 25 | 25 | 0.0% |
| 两空格缩进对象 | 56 | 25 | 55.4% |
| 四空格缩进对象 | 76 | 25 | 67.1% |
| 两空格缩进数组(8 元素) | 42 | 17 | 59.5% |
| 值含换行符的对象 | 20 | 15 | 25.0% |
边界与精度
体积阈值分两档。输入超过 200 KB(204800 字节)时先在提示区说明「已进入大文本处理」,让用户知道会有短暂停顿;超过 2 MB(2097152 字节)直接拒绝并报错,提示改用命令行工具。参考量级:2 万条记录的数组格式化后约 1482 KB,本页压缩后约 818 KB、压缩率 44.8%,Node 侧实测耗时 9 毫秒——单页内跑得动,但再大就会让标签页卡住,所以设了硬上限。
最危险的边界是数字精度,不是体积。JSON 的数字字面量在 JSON.parse 里直接落成 IEEE 754 双精度数,安全整数上限是 253-1 = 9007199254740991。所以 12345678901234567890(订单号、雪花 ID 常见)会被解析成 12345678901234567000,末位被静默改掉,压缩过程不报任何错。长 ID 必须写成字符串,这是唯一可靠的做法。另一个方向的坑是 1e400:解析得到 Infinity,而 JSON 没有 Infinity,stringify 会写出 null。
BOM 绝不能带。实测 JSON.parse('\ufeff{"a":1}') 直接抛 SyntaxError: Unexpected token,因为 U+FEFF 不是 JSON 合法字符。所以本页「下载 JSON」写出的文件首字节是 7b({),不带 ef bb bf。本页的 CSV 导出是另一回事——那是给 Excel 看的表格,必须带 BOM,否则中文列名会乱码。
每条非法输入都指名报错。空输入报「输入框是空的」;带尾逗号 {"a":1,} 报「第 7 个字符附近多了逗号」;单引号 {'a':1} 报「JSON 的键和字符串都必须用双引号」;{"a":01} 报「第 6 个字符处的前导零不合法」;{"a":1} {"b":2} 报「第 8 个字符后有多余内容,一个 JSON 只能有一个顶层值」。全部给出位置和改法,不静默返回空串。
常见问题
压缩后数据变了,是不是工具出错?
要看变的部位。空白、缩进、换行被去掉是压缩的定义;而数字和转义序列被改写是 JSON.parse 的解析规则,属正常行为。最需要警惕的是大整数末位被改(12345678901234567890 → 12345678901234567000)和 1e400 变 null,这两种请把源数据里的数字改成字符串。
为什么不用正则删空白,那样更快也更简单?
因为正则分不清语法空白和字符串内容。{"s":" 空格 "} 会被删成 {"s":"空格"},数据被改且无提示。parse 阶段已经把语法空白丢掉,字符串值完整保存在对象里,再由 stringify 按标准输出,值一个字符都不会少。
压缩率 0% 是不是说明没生效?
说明输入本来就已经是最小形式了。实测对已压缩文本再压一次,省下 0 个字符,这是正常的幂等结果,不是故障。压缩率是「相对输入」算的,输入没冗余自然就是 0%。
为什么我的订单号压完末尾变了?
因为订单号是 19 到 20 位的整数,超出双精度安全整数上限 9007199254740991(253-1)。JSON.parse 用 Number 接住它,末几位被四舍五入。把订单号改成字符串 "12345678901234567890" 再压,值就原样保住了。
字符串里的换行会被折成一行吗?
不会。值里的换行在 JSON 里必须写成转义符 \n 两个字符,parse 读成实际换行字符,stringify 再转回 \n,所以输出永远是单行且数据无损。对照表里 {"s":"line1\nline2"} 这一行压缩前后完全一致。
下载的 .json 文件能不能直接上传到接口?
能。本页下载的文件不带 BOM,首字节就是 {。这正是本页和 CSV 导出的关键区别:CSV 是给 Excel 读的,必须带 BOM 才不乱码;JSON 交给机器读,带 BOM 反而会让 JSON.parse 抛 Unexpected token。
尾逗号、单引号、注释为什么不放过?
因为 JSON 语法由 ECMA-404 和 RFC 8259 严格定义,这三者都不合法。允许它们的是 JSON5 或 JSONC,那是另一套方言。本页的判断是「这段文本是不是合法 JSON」,不是「作者大概想表达什么」,所以一律报错并指出位置。
几 MB 的文件能处理吗?
超过 200 KB 会先提示,进入大文本处理;超过 2 MB 直接拒绝并建议改用命令行工具。参考量级是 2 万条记录约 1482 KB,压缩后 818 KB、实测 9 毫秒。单页能跑这个量级,再大就会让标签页无响应,所以设了硬阈值而不是让它卡死。