JSON 压缩

把 JSON 压缩到最小合法形式,或用 2 空格、4 空格、制表符重新格式化。支持键名排序,实时显示节省字节数,全程在浏览器内完成。

去掉所有不影响数据的字节。 粘贴 JSON 即可移除全部可选空白,也可以切换到美化模式,用你偏好的缩进重新排版。键名排序让两份文档可以直接对比,字节计数则告诉你这次压缩到底省下了多少。

压缩到底做了什么,又没做什么

只删除空白

JSON 语法允许在任意两个词法单元之间放置空格、制表符和换行,而这些字符都不携带任何含义。所谓压缩,就是把这些可选字符全部去掉:{"a": 1, "b": 2} 变成 {"a":1,"b":2}。解析后的值在内存中完全一致,因此在发送数据前做这一步永远是安全的。

压缩不做的事情是「压缩数据」。键名、字符串内容和数字精度都被原样保留。如果你的文档很大是因为在一万条记录里重复了同样的二十个字段名,压缩只能省掉缩进,重复本身依然存在——那是 gzip 或者换一套数据结构才能解决的问题。

什么时候这点节省才真的有意义

一份典型的格式化 API 响应中,空白大约占原始体积的 10% 到 30%。这听上去很可观,但别忘了几乎所有 HTTP 响应在传输时都已经过 gzip 或 brotli 压缩,而压缩算法处理连续空格的效率极高。经过 gzip 之后,压缩版与格式化版 JSON 的差距往往不到 2%。

压缩仍然在三种场景里站得住脚:直接内联进 HTML 页面或 JavaScript 包的数据,因为它们不会被单独压缩;存进数据库字段或缓存的数据,因为占空间的正是原始字符串;以及任何需要与硬性长度上限较劲的地方,例如 URL 参数或有固定长度限制的消息字段。

用键名排序做对比

JSON 对象在规范上是无序的,但每个序列化实现都会按某个具体顺序写出键名,而两套系统很少会选一样的顺序。于是两份逻辑完全相同的文档做纯文本 diff 时会一片红。

在输出前递归地对键名排序,能让两份文档得到相同的规范形态,行级 diff 这才只显示真正的差异。可复现构建和内容寻址缓存背后用的也是同一招。但要记住:排序会改变输出的字节内容,排序后的文档不再与源系统产出的完全一致——它适合用来对比,不适合用来回传需要校验签名的数据。

开源说明:使用原生 JavaScript 实现,不依赖第三方库。

常见问题

我的数据会被上传吗?
不会。解析和重新序列化全部使用浏览器内置的 JSON 函数在本地完成,文档不会离开这个页面。
压缩会改变我的数据吗?
不会。被移除的只是词法单元之间无意义的空白。所有键、字符串、数字和布尔值都原样保留,解析结果完全一致。
为什么节省的字节比我预期少?
计数器统计的是原始 UTF-8 字节数。如果你的 JSON 本来就比较紧凑,或者体积主要来自字符串内容而非缩进,那可删的空白自然就不多。
服务器已经开了 gzip,还需要压缩吗?
网络传输场景通常不需要——gzip 处理连续空格的效率很高,额外收益往往不到 2%。但对内联或落库存储的 JSON 仍然有用。
键名排序有什么用?
它会递归地把每个对象的键按字母顺序重排。两份逻辑相同的文档因此得到完全相同的文本,行级 diff 才真正可用。
看起来没问题的 JSON 为什么报解析错误?
严格语法不接受尾随逗号、单引号字符串、注释和不带引号的键名。那些是 JavaScript 对象字面量的特性,不属于 JSON。