使用方法
- 打开页面就有一组完整结果:输入框已经填入一份示例 JSON,结果区已经给出键排序后的格式化文本,不需要先填任何东西。
- 想排序自己的数据,就把输入框里的示例整段替换成你的 JSON;对象里的键会被递归排序,但数组里元素的先后不会动。
- 输入框按 Ctrl 或 Cmd 加回车会立即排序;也可以每敲一个字就实时看到结果。结果区第一行是排序后的 JSON 文本,可直接复制。
- 如果 JSON 写错了(少括号、多逗号、引号不配对),结果区会给出具体的解析错误,并点名出错原因,方便你定位。
- 结果区下面是「排序示例对照表」,列出 14 组输入与其排序后的首层键序,方便你核对排序规则是否理解正确。
- 本页不联网、不写本地存储,刷新即回到默认示例;你输入的 JSON 只在本机内存里算完即弃。
这个JSON按键排序工具能解决什么
这个JSON按键排序工具帮你把杂乱的 JSON 整理成键有序的形态。最常见的场景是比对两份结构相近的配置或接口返回:当键的顺序不一样时,文本 diff 会满屏飘红,而先统一排序再比对,差异就只剩真正的内容变动,一眼可见。
第二类场景是人工审阅。人眼读一段键乱放的对象很累,排过序后同类字段挨在一起,抽查某个字段在不在、值对不对都更快。对多层嵌套的配置尤为明显。
第三类场景是稳定输出。有些系统序列化 JSON 时键顺序不确定,做快照、做缓存键、做签名时顺序变了就会被认为「变了」。先按固定字母序排一遍,输出就稳定可复现。
必须写清的边界:本工具只排「对象的键」,不排数组元素、也不排对象里的标量值本身。也就是说,数组 [3,1,2] 排序后仍是 [3,1,2],字符串、数字、布尔也不会被改;它做的是结构整理,不是数据排序。
第四类场景是教学与排查。给新手演示 JSON 结构时,键排序后的对象更容易讲清楚层级关系;排查「为什么两份数据被认为不一致」时,先统一键序再比对,能快速排除「只是顺序不同」这类假差异,把注意力留给真正的值变化。它不依赖任何服务端与库,离线也能用,适合写进文档或脚本里反复调用。
递归排序与数组判定的原理
算法是递归的:遇到一个对象,先取它的全部键做字母升序排序,再按新顺序把每个键对应的值递归地再过一遍;遇到数组,则保持原顺序,只对其中的每一个元素递归处理;遇到字符串、数字、布尔、null 这类标量就原样返回。这样无论嵌套多深,每一层的对象键都会被排好。
关键点在于「怎么判断是不是数组」。普通 typeof [] 是 'object',和对象分不清;跨框架(不同 iframe、不同 realm)时 instanceof Array 还会失灵。所以本页用 Object.prototype.toString.call(v) === '[object Array]' 来判定,这条写法不受 realm 影响,是最稳的数组判据。
排序用的是 JavaScript 原生的字符串默认排序(按 UTF-16 码元升序),所以大写字母排在小写字母前面(Z 在 a 前)、数字按字符逐位排("10" 在 "2" 前)。下面这张变量表列出了本页用到的判定量与取值含义。
关于排序的稳定性还有一点值得说明:原生 sort 对键名做字符串比较,而同一层的对象键在 JSON 里天然唯一,不会出现重复键,因此不会因为「相同键名」引发顺序抖动;也正因键唯一,递归重排不会产生键覆盖,每一层输出的键集合与输入完全一致,只是顺序变了。你可以用它做可复现的输出,而不必担心排着排着丢了某个字段。
| 变量 | 含义 | 取值 | 影响 |
|---|---|---|---|
| input | 原始 JSON 文本 | 任意合法 JSON | 排序的唯一输入 |
| v | 遍历中的值 | 对象 / 数组 / 标量 | 决定走排序还是原样返回 |
| isArr | 数组判定 | toString.call(v)==='[object Array]' | 为真才保留元素顺序 |
| keys | 排序后的键 | 字母升序的键名列表 | 决定对象输出顺序 |
完整示例
默认示例是 {"name":"Bob","age":30,"tags":["b","a"],"meta":{"z":1,"a":2}}。首层四个键 name、age、tags、meta 排序后变成 age、meta、name、tags;其中 meta 是个对象,它的键 z、a 也被排成 a、z;而 tags 是数组 ["b","a"],顺序原样保留。结果区里那一整段就是:
{
"age": 30,
"meta": {
"a": 2,
"z": 1
},
"name": "Bob",
"tags": [
"b",
"a"
]
}
把输入换成 {"b":1,"a":2},输出就是 {"a":1,"b":2};换成 {"name":"x","age":1,"z":9},首层键排序后是 age、name、z。两个结果都是当场算出来的,不是写死的。
需要特别留意的是 meta 内部的 a、z 排序与首层无关:它们是 meta 这一层的键,所以只在这一层内按字母排,不会因为首层已经有了 age、name、tags 就被拉平到顶层。递归的边界正是这样一层一层各自独立、互不串扰——你甚至可以嵌套十几层,每一层都只管自己这一层的键顺序,不会向上或向下泄漏。理解了这一点,就能放心把它用在任意深度的真实报文上。
排序示例对照表
下表共 14 行:覆盖单层、多层、含数组、含大小写、含数字键等典型输入。每行的「排序后首层键序」都由页面里的同一套递归函数现场算出,和你在上方输入框里得到的结果用的是同一套逻辑;默认显示 12 行,点「加载更多」看余下 2 行。
| 示例输入 | 排序后首层键序 |
|---|---|
| {"b":1,"a":2} | a, b |
| {"name":"x","age":1,"z":9} | age, name, z |
| {"x":1,"y":2,"z":3,"a":4} | a, x, y, z |
| {"c":{},"a":{},"b":{}} | a, b, c |
| {"keep":[3,1,2],"order":[9,8]} | keep, order |
| {"Z":1,"a":2} | Z, a |
| {"age":30,"meta":{"z":1,"a":2}} | age, meta |
| {"1":1,"10":2,"2":3} | 1, 10, 2 |
| {"_":1,"a":2} | _, a |
| {"a":[1,2],"b":{"y":1,"x":2}} | a, b |
| {"A":2,"a":1} | A, a |
| {"data":{"nested":{"c":1,"b":2,"a":3}}} | data |
| {"b":1,"a":[5,3,4]} | a, b |
| {"z":1,"y":2,"x":3,"w":4} | w, x, y, z |
横向读这张表能得出两条实用结论:第一,数组顺序永远不动(keep、order 那一行,以及任何带数组的例子),因为只有对象的键才被排序;第二,排序是字符串序而非数字序,"1"、"10"、"2" 排出来是 1、10、2,大写 Z 也排在小写 a 前面。
结果边界与错误提示
- 输入框为空时,会自动填回默认示例并立即排序,不会留下空白结果。
- JSON 解析失败时,提示点名具体原因:「JSON 解析失败:<错误信息>。请检查括号、逗号与引号是否成对」,不会静默返回空。
- 数组里的元素顺序一律保留,不会被排序,无论里面是数字、字符串还是对象。
- 对象里的标量值(字符串、数字、布尔、null)原样保留,只动键的顺序,不改数据内容。
- 排序用的是 UTF-16 码元升序:大写字母小于小写字母,数字按字符逐位比较,与数值大小无关。
- 极深的嵌套在理论上可能触发调用栈上限;普通业务 JSON 远不到这个量级,本页未做特殊兜底。
- 本页不上传任何输入,也不写本地存储;导出的对照表 CSV 带字节序标记,复制结果为纯文本(本页对照表以 TSV 复制)。
常见问题
为什么我的数组被排了序?
如果你看到数组顺序变了,几乎一定是把数组误写成了对象,或者本想排对象却贴了一段别的内容。本工具的数组判定用 Object.prototype.toString.call,标准写法下的数组会严格保持原顺序,只有对象的键才会被排序。
大写字母为什么排在小写前面?
因为排序按字符的 UTF-16 码元比较,大写字母(如 Z,码元 90)小于小写字母(如 a,码元 97)。这是 JavaScript 的默认字符串排序行为,数字字符同理按字符逐位比,所以 "10" 会排到 "2" 前面。
数字键的排序符合直觉吗?
不符合数值直觉,但符合字符串直觉。"1"、"10"、"2" 按字符逐位比较会得到 1、10、2,因为 "1" 与 "10" 首位都是 "1","10" 的第二位 "0" 小于 "2" 的首位 "2"。若想按数值排,需要先把键转成数字再排,本工具不做这步。
跨 iframe 的数组会被判错吗?
不会。本页用 Object.prototype.toString.call(v) === '[object Array]' 判定数组,这条写法不受 realm 影响;相比之下用 instanceof Array 在跨 iframe 时才可能失灵,所以这里特意避开了它。
嵌套多少层都没问题吗?
递归对普通业务 JSON 完全够用。只有极深(成千上万层)的嵌套才可能触及调用栈上限,正常配置与接口返回远达不到,本页没有为这种极端情况做专门兜底。
排序后值会变吗?
不会。排序只重新排列「对象的键」,字符串、数字、布尔、null 这些标量原样保留,数组元素顺序也保留。它做的是结构整理,不是数据重排,所以你可以用它来稳定输出而不改变语义。
我的 JSON 会被上传吗?
不会。整个排序过程都跑在你的浏览器本地,文本只存在于本机内存,页面既不发请求也不写本地存储,刷新后输入框回到默认示例。
为什么对照表用 TSV 复制而不是 CSV?
对照表是展示性的小表,用制表符分隔文本复制最轻量,粘进表格软件会自动分列;它不是 CSV 文件导出场景,所以不需要 BOM 与引号转义那一套。
相关工具
- CSV转JSON转换器:把 CSV 表格转换成 JSON 数组。
- JSON校验工具:校验并格式化 JSON 文本。
- HTML格式化:缩进与整理 HTML 代码结构。
- JSON格式化工具:把压缩 JSON 美化或压缩。
- JWT解码:拆解 JWT 三段结构并解码载荷。