Compare two deep nested object of objects and return only the differences in javascript / lodash

557
February 17, 2017, at 02:11 AM

I have 2 deep nested object of objects. One is a "base" object and the other is a modified one.

I essentially want to "delete" the base object from the modified object and return an object that only contains different data. Here is an example:

Base object:

baseObj : {
    image: {
        width: '100%',
        paddingTop: '0px',
        paddingRight: '0px',
        paddingBottom: '0px',
        paddingLeft: '0px'
    },
    wrap: {
        marginTop: '0px',
        marginRight: '0px',
        marginBottom: '0px',
        marginLeft: '0px'
    }
}

Object with modified data

mergedObject : {
    image: {
        width: '100%',  
        paddingTop: '0px',
        paddingRight: '24px', // modified value
        paddingBottom: '24px', // modified value
        paddingLeft: '0px'
    },
    wrap: {
        height: '100px', // new value
        marginTop: '24px', // modified value
        marginRight: '0px',
        marginBottom: '0px',
        marginLeft: '24px' // modified value
    }
}

I would like an object that is returned like this:

diffObject : {
    image: {
        paddingRight: '24px',
        paddingBottom: '24px',
    },
    wrap: {
        height: '100px',
        marginTop: '24px',
        marginLeft: '24px'
    }
}

The nesting could go a little deeper so it needs to be dynamic. Is there a way using lodash or some other library?

Answer 1

you could use recursive function to find the last object.

var checkIfObject = function(item){ //recursive function
_.each(item, function(v, k){
if(_.isObject(v)){
previousObject = k;
previousResult = v;
return checkIfObject(v);
}else{
    finalChildObjects[previousObject] = previousResult;
}
})
return finalChildObjects
}
/*Initialize Values for recursive function*/
var finalChildObjects = {};
var previousObject = '';
var previousResult = '';
baseObjectFinalTurn = checkIfObject(baseObj);
/*Initialize Values for recursive function*/
var finalChildObjects = {};
var previousObject = '';
var previousResult = '';
mergedObjectFinalTurn = checkIfObject(mergedObject);
console.clear();

var difference = {};
_.each(baseObjectFinalTurn, function(v, k){
    if(mergedObjectFinalTurn[k]){
    difference[k] = _.reduce(mergedObjectFinalTurn[k],function(result, value, key){
    if(baseObjectFinalTurn[k][key] != mergedObjectFinalTurn[k][key]){
    result[key] =  value;
    }
    return result
    }, {})
  }
  else{
  difference[k] = {};
  }
})
console.log(difference)

You can verify the result from this jsfiddle link

Note: you need to adjust the result based on your requirement in reduce. This result is made to match your output.

Rent Charter Buses Company
READ ALSO
Can I create a native windows desktop application using Node.js

Can I create a native windows desktop application using Node.js

So I have heard of http://appjscom/ and http://electron

381
How can I check `bin/` directories under `node_modules/` into TFS?

How can I check `bin/` directories under `node_modules/` into TFS?

I have a Team Foundation Build server behind a firewall, and I would like to check in a node_modules/ directory (powering both a Browserify client app and Node server app) associated with a project so that all of the files and dependencies needed to deploy...

359
Application-side join ORM for Node?

Application-side join ORM for Node?

To start: I've tried LoopbackLoopback is nice but does not allow for relations across multiple REST data services, but rather makes a call to the initial data service and passes query parameters that ask it to perform the joined query

336
Export on nodejs alpine docker image is not accepted

Export on nodejs alpine docker image is not accepted

I want to add a http_proxy environment variable to the nodejs alpine docker image

495