一尘不染

获取两个JSON对象的差异

json

场景:我想要一个比较两个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"}]};

或类似的东西,你就明白了。

有人知道解决方案吗?我已经找到了一个插件,但是我想知道是否还有其他选择。


阅读 477

收藏
2020-07-27

共1个答案

一尘不染

可以使用通过对象键进行迭代的递归函数。然后使用Object.is测试NaNnull。然后测试如果第二对象是流延到该类型false喜欢0NaNnull。列出两个对象的键并将它们连接起来以测试中缺少的键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;
}

测试:http//jsfiddle.net/gartz/Q3BtG/2/

2020-07-27