出于某种原因,接受的答案对我来说不适用于嵌套对象。这导致我自己编写代码。当我写这篇文章时,已经是 2019 年末了,该语言中还有更多可用的选项。
更新:我相信大卫弗隆的回答比我之前的尝试更可取,我对此嗤之以鼻。我的依赖于对 Object.entries(...) 的支持,因此不支持 Internet Explorer。
function normalize(sortingFunction) {
return function(key, value) {
if (typeof value === 'object' && !Array.isArray(value)) {
return Object
.entries(value)
.sort(sortingFunction || undefined)
.reduce((acc, entry) => {
acc[entry[0]] = entry[1];
return acc;
}, {});
}
return value;
}
}
JSON.stringify(obj, normalize(), 2);
--
保留此旧版本以供历史参考
我发现对象中所有键的简单、扁平数组将起作用。在几乎所有浏览器(不是 Edge 或 Internet Explorer,可以预见)和 Node 12+ 中,现在Array.prototype.flatMap(...)可用,因此有一个相当短的解决方案。(lodash 等价物也可以。)我只在 Safari、Chrome 和 Firefox 中进行了测试,但我看不出它为什么不能在支持 flatMap 和标准JSON.stringify(...)的其他任何地方工作。
function flattenEntries([key, value]) {
return (typeof value !== 'object')
? [ [ key, value ] ]
: [ [ key, value ], ...Object.entries(value).flatMap(flattenEntries) ];
}
function sortedStringify(obj, sorter, indent = 2) {
const allEntries = Object.entries(obj).flatMap(flattenEntries);
const sorted = allEntries.sort(sorter || undefined).map(entry => entry[0]);
return JSON.stringify(obj, sorted, indent);
}
有了这个,您可以在没有 3rd 方依赖项的情况下进行字符串化,甚至可以传入您自己的排序算法,该算法对键值条目对进行排序,因此您可以按键、有效负载或两者的组合进行排序。适用于嵌套对象、数组和普通旧数据类型的任何混合。
const obj = {
"c": {
"z": 4,
"x": 3,
"y": [
2048,
1999,
{
"x": false,
"g": "help",
"f": 5
}
]
},
"a": 2,
"b": 1
};
console.log(sortedStringify(obj, null, 2));
印刷:
{
"a": 2,
"b": 1,
"c": {
"x": 3,
"y": [
2048,
1999,
{
"f": 5,
"g": "help",
"x": false
}
],
"z": 4
}
}
如果您必须与较旧的 JavaScript 引擎兼容,您可以使用这些稍微冗长的版本来模拟 flatMap 行为。客户端必须至少支持 ES5,所以不支持 Internet Explorer 8 或更低版本。
这些将返回与上述相同的结果。
function flattenEntries([key, value]) {
if (typeof value !== 'object') {
return [ [ key, value ] ];
}
const nestedEntries = Object
.entries(value)
.map(flattenEntries)
.reduce((acc, arr) => acc.concat(arr), []);
nestedEntries.unshift([ key, value ]);
return nestedEntries;
}
function sortedStringify(obj, sorter, indent = 2) {
const sortedKeys = Object
.entries(obj)
.map(flattenEntries)
.reduce((acc, arr) => acc.concat(arr), [])
.sort(sorter || undefined)
.map(entry => entry[0]);
return JSON.stringify(obj, sortedKeys, indent);
}