Sor*_*ami 26 javascript diff jquery json
场景:我想要一个比较两个JSON对象的函数,并返回一个带有差异列表的JSON对象,如果可能的话还有更多数据,例如覆盖度量.
var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';
Run Code Online (Sandbox Code Playgroud)
如果我运行compare(madrid, barca)返回的对象可能看起来像:
{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]};
Run Code Online (Sandbox Code Playgroud)
或类似的东西,你明白了.
有谁知道这个解决方案?我已经找到了一个插件,但我想知道是否还有其他选择.
Gab*_*rtz 35
可以使用通过对象键迭代的递归函数.然后使用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;
}Run Code Online (Sandbox Code Playgroud)
上面的代码是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;
}
Run Code Online (Sandbox Code Playgroud)
测试:http://jsfiddle.net/gartz/Q3BtG/2/
您可以使用rus-diff https://github.com/mirek/node-rus-diff创建兼容MongoDB(重命名/取消设置/设置)差异:
// npm install rus-diff
var madrid = {"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]};
var barca = {"type":"team","description":"Bad","trophies":[{"ucl":"3"}]};
var rusDiff = require('rus-diff').rusDiff
console.log(rusDiff(madrid, barca))
Run Code Online (Sandbox Code Playgroud)
输出:
{ '$unset': { 'trophies.1': true },
'$set': { description: 'Bad', 'trophies.0.ucl': '3' } }
Run Code Online (Sandbox Code Playgroud)
贡献我对Gabriel Gartz版本的改动.这个工作在严格模式下并删除数组检查 - 将始终为false.它还从diff中删除空节点.
//http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
var isEmptyObject = function(obj) {
var name;
for (name in obj) {
return false;
}
return true;
};
//http://stackoverflow.com/questions/8431651/getting-a-diff-of-two-json-objects
var diff = function(obj1, obj2) {
var result = {};
var change;
for (var key in obj1) {
if (typeof obj2[key] == 'object' && typeof obj1[key] == 'object') {
change = diff(obj1[key], obj2[key]);
if (isEmptyObject(change) === false) {
result[key] = change;
}
}
else if (obj2[key] != obj1[key]) {
result[key] = obj2[key];
}
}
return result;
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45952 次 |
| 最近记录: |