It's not too hard to create a function like this. Just loop through each field in the second object, and if it's not present in the first or the value is different than the first, put that field in the return object.
var compareJSON = function(obj1, obj2) {
var ret = {};
for(var i in obj2) {
if(!obj1.hasOwnProperty(i) || obj2[i] !== obj1[i]) {
ret[i] = obj2[i];
}
}
return ret;
};
You can see it in action on this demo page.
Answer from Peter Olson on Stack Overflow
» npm install json-diff
It's not too hard to create a function like this. Just loop through each field in the second object, and if it's not present in the first or the value is different than the first, put that field in the return object.
var compareJSON = function(obj1, obj2) {
var ret = {};
for(var i in obj2) {
if(!obj1.hasOwnProperty(i) || obj2[i] !== obj1[i]) {
ret[i] = obj2[i];
}
}
return ret;
};
You can see it in action on this demo page.
You can have a look at json diff wrapper here
It has also demo page.You can use this wrapper.
» npm install json-diff-kit
» npm install json-diff-ts
It's possible to use a recursive function that iterates by the object keys. Then use the Object.is to 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.
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.
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.
Test link: 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.
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;
}
Tests: http://jsfiddle.net/gartz/Q3BtG/2/
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.
//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;
};
» npm install diff-json
Friends! I'm really sorry if I don't understand something, or explain question in wrong terms. All I wanna do is to compare the equality of two pieces of JSON-standardized data like this:
{"skip":0, "limit":7, "arr": [1682, 439, {"x":2, arr:[]}] }
{"skip":0, "limit":7, "arr": [1682, 450, "a", ["something"] }
I'm 100% sure there will be no functions, Date, null or undefined, etc. in these data. I want to say I don't want to compare JavaScript objects in the most general case (with complex prototypes, circular links and all this stuff). The prototype of these data will be Object. I'm also sure lots of skillful programmers have answered this question before me.
The main thing I'm missing is that I don't know how to explain my question correctly. Please feel free to edit my post.
My answer:
First way: Unefficient but reliable. You can modify a generic method like this so it does not waste time looking for functions and undefined. Please note that generic method iterates the objects three times (there are three for .. in loops inside)
Second way: Efficient but has one restriction. I've found JSON.stringify is extremely fast in node.js. The fastest solution that works is:
JSON.stringify(data1) == JSON.stringify(data2)
Very important note! As far as I know, neither JavaScript nor JSON don't matter the order of the object fields. However, if you compare strings made of objects, this will matter much. In my program the object fields are always created in the same order, so the code above works. I didn't search in the V8 documentation, but I think we can rely on the fields creation order. In other case, be aware of using this method.
In my concrete case the second way is 10 times more efficient then the first way.
I've done some benchmarking of the various techniques, with underscore coming out on top:
> node nodeCompare.js
deep comparison res: true took: 418 (underscore)
hash comparison res: true took: 933
assert compare res: true took: 2025
string compare res: true took: 1679
Here is the source code:
var _ = require('underscore');
var assert = require('assert');
var crypto = require('crypto');
var large = require('./large.json');
var large2 = JSON.parse(JSON.stringify(large));
var t1 = new Date();
var hash = crypto.createHash('md5').update(JSON.stringify(large)).digest('hex');
var t2 = new Date();
var res = _.isEqual(large, large2);
var t3 = new Date();
var res2 = (hash == crypto.createHash('md5').update(JSON.stringify(large2)).digest('hex'));
var t4 = new Date();
assert.deepEqual(large, large2);
var t5 = new Date();
var res4 = JSON.stringify(large) === JSON.stringify(large2);
var t6 = new Date();
console.log("deep comparison res: "+res+" took: "+ (t3.getTime() - t2.getTime()));
console.log("hash comparison res: "+res2+" took: "+ (t4.getTime() - t3.getTime()));
console.log("assert compare res: true took: "+ (t5.getTime() - t4.getTime()));
console.log("string compare res: "+res4+" took: "+ (t6.getTime() - t5.getTime()));
Grab json-diff from npm - https://www.npmjs.com/package/json-diff
Or, just have a look at the source code and do whatever he did. - https://github.com/andreyvit/json-diff
There are some packages out there on npm that appear to do this (https://github.com/NV/objectDiff.js).
If efficiency is not a concern, you can just do a scan, where you loop across json1, and for every element see if it exists in json2, and then vice versa. In this case, since you're only looking for these name KVPs, you could also just normalize it into ['apple', 'mango', 'orange'] and ['apple', 'mango'] and use indexOf().
» npm install json-schema-diff