场景:我想要一个比较两个 JSON 对象的函数,并返回一个带有差异列表的 JSON 对象,如果可能的话,还需要更多数据,例如覆盖率指标。
var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';
如果我运行 compare(madrid, barca)
,返回的对象可能类似于:
{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]};
或者类似的东西,你懂的。
有人知道这个问题的解决方案吗?我已经找到了一个plugin ,但我想知道是否有其他选择。
最佳答案
可以使用通过对象键迭代的递归函数。然后使用 Object.is测试 NaN
和 null
。然后测试第二个对象是否是转换为 false
的类型,例如 0
、NaN
或 null
。
列出两个对象的键并将它们连接起来以测试 obj1
中缺少的键,然后对其进行迭代。
当相同键值有差异时,存储object2
的值并继续。如果两个键值都是对象,则意味着可以递归比较,因此可以。
function diff(obj1, obj2) {
const result = {};
if (Object.is(obj1, obj2)) {
return undefined;
}
if (!obj2 || typeof obj2 !== 'object') {
return obj2;
}
Object.keys(obj1 || {}).concat(Object.keys(obj2 || {})).forEach(key => {
if(obj2[key] !== obj1[key] && !Object.is(obj1[key], obj2[key])) {
result[key] = obj2[key];
}
if(typeof obj2[key] === 'object' && typeof obj1[key] === 'object') {
const value = diff(obj1[key], obj2[key]);
if (value !== undefined) {
result[key] = value;
}
}
});
return result;
}
上面的代码是 BSD 许可的,可以在任何地方使用。
测试链接:https://jsfiddle.net/gartz/vy9zaof2/54/
一个重要的观察,这会将数组转换为对象并比较相同索引位置的值。由于所需的额外复杂性,还有许多其他方法可以比较此函数未涵盖的数组。
编辑 2/15/2019:此答案已更改为添加新的 ES2017 语法并修复评论中的用例。
这只是一个开始,我还没有测试过,但我从一个过滤器或比较器函数开始,它是递归的,可以根据需要进行更改以获得优先结果。
function filter(obj1, obj2) {
var result = {};
for(key in obj1) {
if(obj2[key] != obj1[key]) result[key] = obj2[key];
if(typeof obj2[key] == 'array' && typeof obj1[key] == 'array')
result[key] = arguments.callee(obj1[key], obj2[key]);
if(typeof obj2[key] == 'object' && typeof obj1[key] == 'object')
result[key] = arguments.callee(obj1[key], obj2[key]);
}
return result;
}
关于javascript - 获取两个 json 对象的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8431651/