JSON 格式化 / 压缩 / 校验JSON 转义 / 去转义JSON 对比JSON 键排序JSON 转字符串 / 字符串转 JSONJSON 转 XMLXML 转 JSONJSON 数组转 CSVCSV 转 JSON 数组JSON 与 YAML 互转JSON 生成代码定义查询参数与 JSON 互转Cookie 与 JSON 互转JSON 与 Properties 互转
JSON 键排序
按字母顺序递归排序所有对象的键名
JSON 键排序:为什么要排,以及排序会破坏什么
排序是安全的——在语义层面
JSON 规范规定对象是无序的键值集合,键的出现顺序不携带任何语义。所以把一个对象的键按字母排序,得到的仍然是同一份数据,任何合法的解析器都会认为两者等价。
这一点让排序成为一种安全的规范化手段。它的三个主要用途:
- 让 diff 变干净。两边的键顺序一致后,文本 diff 就只会标出真正变化的字段,而不会因为顺序差异满屏红绿。这对配置文件的版本管理和接口响应的对比非常有用。
- 让输出可复现。构建产物、代码生成、快照测试里,同样的输入必须产生逐字节相同的输出,否则 CI 会一直报假差异。
- 让哈希稳定。JSON 常用于生成签名和缓存键。键顺序不同会导致序列化字符串不同,从而得到不同的哈希——同一个对象算出两个签名,缓存全部失效、签名校验失败。排序(配合数字格式规范化)是解决这个问题的标准做法,这个流程叫 JSON 规范化,RFC 8785(JCS)给出了完整定义。
排序会破坏什么
规范说顺序无意义,但现实里有很多东西依赖顺序:
- 数组的顺序绝对不能动。数组是有序集合,
[1,2,3]和[3,2,1]是不同的数据。排序时必须只处理对象的键,把数组原样保留。如果工具对数组元素也排序,它会静默地改掉你的数据。 - 展示顺序。有些系统直接按 JSON 的键顺序渲染表单、表格列或菜单项。排序会让你精心安排的界面顺序变成字母序。
- 依赖插入顺序的下游。某些语言的对象实现(如 JavaScript 对字符串键)会保留插入顺序,而有些业务逻辑会利用这一点做隐式排序。排序会改变这些行为。
- 人工维护的配置。把相关配置项排在一起的意图(比如把
host和port挨着写)会被字母序打散,可读性反而下降。
结论:排序适合"机器消费"的 JSON(签名、缓存键、快照、CI 产物),不适合"人阅读和维护"的配置,除非你接受字母序带来的可读性损失。
排序规则里的细节
| 问题 | 处理方式 |
|---|---|
| 大小写混排 | 区分大小写时大写字母排在小写之前(ASCII 序),Z 在 a 前面。要人眼友好可先统一大小写再排。 |
| 数字键 | "10" 按字符串排在 "9" 之前。要自然序需要按数值比较。 |
| 非 ASCII 键 | 按 UTF-16 码元比较与按 Unicode 码点比较,结果可能不同(涉及代理对)。要求跨语言一致时须明确指定。 |
| 嵌套对象 | 需要区分"只排顶层"和"递归排每一层"。递归排才是规范化需要的。 |
另外要注意:排序不解决重复键。JSON 里出现两个同名键时,排序会把它们排在一起,但数据依然是有问题的(规范未定义重复键行为,多数实现保留最后一个)。发现重复键应该去修数据,而不是排序。
工具怎么用
工具提供顶层排序与递归排序两种模式,可选升序/降序、以及是否保留数组原有顺序(建议保留)。解析失败时会直接报语法错误并给出位置,不会输出被静默改坏的结果。
常见问题
排序会改变数据含义吗?
不会。JSON 对象的键顺序在语义上没有意义,排序仅让输出更易读、方便版本控制中做 diff。
数组会被排序吗?
不会,数组元素顺序是有意义的,本工具只排序对象的键名,数组保持原样。