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.
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:
{"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.
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With