Javascript 获取两个 json 对象的差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8431651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting a diff of two json-objects
提问by Soroush Hakami
Scenario: I want a function that compares two JSON-objects, and returns a JSON-object with a list of the differences and if possible more data such as coverage metrics.
场景:我想要一个函数来比较两个 JSON 对象,并返回一个带有差异列表的 JSON 对象,如果可能的话,还有更多数据,例如覆盖率指标。
var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';
If i ran compare(madrid, barca)
the returned object could look something like:
如果我运行compare(madrid, barca)
返回的对象可能看起来像:
{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]};
Or something similar, you get the idea.
或者类似的东西,你明白了。
Does anyone know of a solution to this? I've already found one plugin, but I'd like to know if there are any alternatives.
有谁知道解决这个问题的方法?我已经找到了一个插件,但我想知道是否还有其他选择。
回答by Gabriel Gartz
It's possible to use a recursive function that iterates by the object keys. Then use the Object.isto test for NaN
and null
. Then test if the second object is the type that cast to false
like 0
, NaN
, or null
.
List the keys of both objects and concatenate them to test of missing keys in the obj1
and then iterate it.
可以使用通过对象键进行迭代的递归函数。然后使用Object.is来测试NaN
和null
。然后测试如果第二对象是流延到该类型false
喜欢0
,NaN
或null
。列出两个对象的键并将它们连接起来以测试 中缺少的键obj1
,然后对其进行迭代。
When there is a difference between the same key values, it stores the value of object2
and proceeds. If both key values are object means that can be recursively compared and so it does.
当相同的键值之间存在差异时,它会存储 的值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;
}
The code above is BSD licensed and can be used anywhere.
上面的代码是 BSD 许可的,可以在任何地方使用。
Test link: https://jsfiddle.net/gartz/vy9zaof2/54/
测试链接:https: //jsfiddle.net/gartz/vy9zaof2/54/
An important observation, this will convert arrays to objects and compare the values in the same index position. There are many other ways to compare arrays not covered by this function due to the required extra complexity.
一个重要的观察,这会将数组转换为对象并比较相同索引位置的值。由于所需的额外复杂性,还有许多其他方法可以比较此函数未涵盖的数组。
EDIT 2/15/2019: This answer was changed to add the new ES2017 syntax and fix use-cases from comments.
编辑 2/15/2019:此答案已更改以添加新的 ES2017 语法并修复注释中的用例。
This is just a kickoff, I haven't tested it, but I began with a filter or comparator function, that is recursive, change it however you need to get priority results.
这只是一个开始,我还没有测试过,但我从一个过滤器或比较器函数开始,这是递归的,改变它但是你需要得到优先结果。
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;
}
回答by Mirek Rusin
You can use rus-diff https://github.com/mirek/node-rus-diffwhich creates MongoDB compatible (rename/unset/set) diff:
您可以使用 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))
Outputs:
输出:
{ '$unset': { 'trophies.1': true },
'$set': { description: 'Bad', 'trophies.0.ucl': '3' } }
回答by Leblanc Meneses
contributing back my changes to Gabriel Gartz version. This one works in strict mode and removes the array check - will always be false. It also removes empty nodes from the diff.
回馈我对 Gabriel Gartz 版本的更改。这个在严格模式下工作并删除数组检查 - 将始终为假。它还从差异中删除空节点。
//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;
};
回答by KARTHIKEYAN.A
Suppose we want to compare two same objects and subtract if object field count match then follow the bellow code.
假设我们要比较两个相同的对象并在对象字段计数匹配时减去,然后按照以下代码进行操作。
var obj1 = {
"Agent": "12819",
"Beneficiary": "476949",
"BillingDetail": "13772",
"BillingInvoice": "914548",
"Claim": "1192",
"Customer": "656320",
"LifeAssured": "228493",
"Payment": "1091661",
"Policy/Proposal": "263196",
"Product": "9",
"ProductComponent": "53",
"ProductComponentOption": "2239791",
"ProductOption": "568785",
"TransactionDetail": "4289240"
}
var obj2 = {
"Agent": "1289",
"Beneficiary": "47694",
"BillingDetail": "13772",
"BillingInvoice": "914548",
"Claim": "1192",
"Customer": "656320",
"LifeAssured": "22893",
"Payment": "1091661",
"Policy/Proposal": "26316",
"Product": "2",
"ProductComponent": "52",
"ProductComponentOption": "223971",
"ProductOption": "56885",
"TransactionDetail": "4289240"
}
function diff(obj1, obj2) {
const result = {};
for(var o1 in obj1){
if(obj2[o1]){
result[o1] = obj1[o1] - obj2[o1];
}
}
return result;
}
console.log(diff(obj1,obj2))
Result:
结果:
{
"Agent": 11530,
"Beneficiary": 429255,
"BillingDetail": 0,
"BillingInvoice": 0,
"Claim": 0,
"Customer": 0,
"LifeAssured": 205600,
"Payment": 0,
"Policy/Proposal": 236880,
"Product": 7,
"ProductComponent": 1,
"ProductComponentOption": 2015820,
"ProductOption": 511900,
"TransactionDetail": 0
}