场景:我想要一个比较两个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"}]};
或类似的东西,你明白了.
有谁知道这个解决方案?我已经找到了一个插件,但我想知道是否还有其他选择.
可以使用通过对象键迭代的递归函数.然后使用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;
}
您可以使用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))
输出:
{ '$unset': { 'trophies.1': true }, '$set': { description: 'Bad', 'trophies.0.ucl': '3' } }
贡献我对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; };