我的应用程序有一大堆对象,我将其字符串化并保存到磁盘.遗憾的是,当数组中的对象被操纵并且有时被替换时,对象上的属性以不同的顺序(它们的创建顺序?)列出.当我对数组执行JSON.stringify()并保存它时,diff会显示以不同顺序列出的属性,这在尝试使用diff和合并工具进一步合并数据时会很烦人.
理想情况下,我想在执行stringify之前按字母顺序对对象的属性进行排序,或者作为stringify操作的一部分.存在用于在许多地方操纵数组对象的代码,并且改变它们以总是以显式顺序创建属性将是困难的.
建议是最受欢迎的!
一个浓缩的例子:
obj = {}; obj.name="X"; obj.os="linux";
JSON.stringify(obj);
obj = {}; obj.os="linux"; obj.name="X";
JSON.stringify(obj);
Run Code Online (Sandbox Code Playgroud)
这两个stringify调用的输出是不同的,并显示在我的数据的差异中,但我的应用程序不关心属性的排序..对象是以多种方式构建的.
mar*_*yzm 62
更简单,现代和当前浏览器支持的方法就是这样:
JSON.stringify(sortMyObj, Object.keys(sortMyObj).sort());
Run Code Online (Sandbox Code Playgroud)
但是,此方法会删除未引用的任何嵌套对象,并且不会应用于数组中的对象.如果你想要这样的输出,你也想要展平排序对象:
{"a":{"h":4,"z":3},"b":2,"c":1}
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
var flattenObject = function(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object') {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
};
JSON.stringify(sortMyObj, Object.keys(flattenObject(sortMyObj)).sort());
Run Code Online (Sandbox Code Playgroud)
要以编程方式使用您可以自行调整的内容,您需要将对象属性名称推送到数组中,然后按字母顺序对数组进行排序并遍历该数组(将按照正确的顺序)并从对象中选择每个值那个命令.还检查"hasOwnProperty",因此您肯定只拥有对象自己的属性.这是一个例子:
var obj = {"a":1,"b":2,"c":3};
function iterateObjectAlphabetically(obj, callback) {
var arr = [],
i;
for (i in obj) {
if (obj.hasOwnProperty(i)) {
arr.push(i);
}
}
arr.sort();
for (i = 0; i < arr.length; i++) {
var key = obj[arr[i]];
//console.log( obj[arr[i]] ); //here is the sorted value
//do what you want with the object property
if (callback) {
// callback returns arguments for value, key and original object
callback(obj[arr[i]], arr[i], obj);
}
}
}
iterateObjectAlphabetically(obj, function(val, key, obj) {
//do something here
});
Run Code Online (Sandbox Code Playgroud)
同样,这应该保证您按字母顺序迭代.
最后,以最简单的方式进一步研究,这个库将以递归方式允许您对传递给它的任何JSON进行排序:https://www.npmjs.com/package/json-stable-stringify
var stringify = require('json-stable-stringify');
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
console.log(stringify(obj));
Run Code Online (Sandbox Code Playgroud)
产量
{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}
Run Code Online (Sandbox Code Playgroud)
Sti*_*itt 34
我认为如果你掌控JSON一代(听起来像你),那么为了你的目的,这可能是一个很好的解决方案:json-stable-stringify
从项目网站:
确定性JSON.stringify(),使用自定义排序从字符串化结果中获取确定性哈希值
如果生成的JSON是确定性的,您应该能够轻松地对其进行差异/合并.
Chr*_*use 25
您可以将属性名称的排序数组作为第二个参数传递JSON.stringify()
:
JSON.stringify(obj, Object.keys(obj).sort())
Run Code Online (Sandbox Code Playgroud)
ale*_*ung 14
更新2018-7-24:
此版本对嵌套对象进行排序并支持数组:
function sortObjByKey(value) {
return (typeof value === 'object') ?
(Array.isArray(value) ?
value.map(sortObjByKey) :
Object.keys(value).sort().reduce(
(o, key) => {
const v = value[key];
o[key] = sortObjByKey(v);
return o;
}, {})
) :
value;
}
function orderedJsonStringify(obj) {
return JSON.stringify(sortObjByKey(obj));
}
Run Code Online (Sandbox Code Playgroud)
测试用例:
describe('orderedJsonStringify', () => {
it('make properties in order', () => {
const obj = {
name: 'foo',
arr: [
{ x: 1, y: 2 },
{ y: 4, x: 3 },
],
value: { y: 2, x: 1, },
};
expect(orderedJsonStringify(obj))
.to.equal('{"arr":[{"x":1,"y":2},{"x":3,"y":4}],"name":"foo","value":{"x":1,"y":2}}');
});
it('support array', () => {
const obj = [
{ x: 1, y: 2 },
{ y: 4, x: 3 },
];
expect(orderedJsonStringify(obj))
.to.equal('[{"x":1,"y":2},{"x":3,"y":4}]');
});
});
Run Code Online (Sandbox Code Playgroud)
弃用答案:
ES2016中的简洁版本.感谢@codename,来自/sf/answers/2073585741/
function orderedJsonStringify(o) {
return JSON.stringify(Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {}));
}
Run Code Online (Sandbox Code Playgroud)
Jor*_*Jor 13
我不明白为什么要递归地获取所有密钥,为什么需要当前最佳答案的复杂性。除非需要完美的性能,在我看来,我们只能打JSON.stringify()
两次电话,第一次是获取所有密钥,第二次是真正完成这项工作。这样,所有递归复杂性都由处理stringify
,我们知道它知道它的内容,以及如何处理每种对象类型?
function JSONstringifyOrder( obj, space )
{
var allKeys = [];
JSON.stringify( obj, function( key, value ){ allKeys.push( key ); return value; } )
allKeys.sort();
return JSON.stringify( obj, allKeys, space );
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*ong 11
https://gist.github.com/davidfurlong/463a83a33b70a3b6618e97ec9679e490
const replacer = (key, value) =>
value instanceof Object && !(value instanceof Array) ?
Object.keys(value)
.sort()
.reduce((sorted, key) => {
sorted[key] = value[key];
return sorted
}, {}) :
value;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
44987 次 |
最近记录: |