deep merge objects with AngularJS

angularjs, javascript

Solution

Angular 1.4 or later

Use `angular.merge`:

Unlike `extend()`, `merge()` recursively descends into object properties of source objects, performing a deep copy.

angular.merge(object1, object2); // merge object 2 into object 1

Older versions of Angular:

There is no reason a simple recursive algorithm shouldn't work :)

Assuming they're both the result of JSON.stringify or similar:

function merge(obj1,obj2){ // Our merge function
    var result = {}; // return result
    for(var i in obj1){      // for every property in obj1 
        if((i in obj2) && (typeof obj1[i] === "object") && (i !== null)){
            result[i] = merge(obj1[i],obj2[i]); // if it's an object, merge   
        }else{
           result[i] = obj1[i]; // add it to result
        }
    }
    for(i in obj2){ // add the remaining properties from object 2
        if(i in result){ //conflict
            continue;
        }
        result[i] = obj2[i];
    }
    return result;
}

Here is a working fiddle

(Note, arrays are not handled here)

Problem

Normally to shallow copy objects I would use `angular.extend()` Here's an example of that: ``` var object1 = { "key": "abc123def456", "message": { "subject": "Has a Question", "from": "example1@example.com", "to": "example2@example.com" } }; var object2 = { "key": "00700916391" }; console.log(angular.extend({}, object1, object2)); ``` Would give us: ``` { "key": "00700916391", "message": { "subject": "Has a Question", "from": "example1@example.com", "to": "example2@example.com" } } ``` But what if I wanted to merge objects so that parent keys are not over written by child objects: ``` var object1 = { "key": "abc123def456", "message": { "subject": "Has a Question", "from": "example1@example.com", "to": "example2@example.com" } }; var object2 = { "key": "00700916391", //Overwrite me "message": { //Dont overwrite me! "subject": "Hey what's up?", //Overwrite me "something": "something new" //Add me } }; console.log(merge(object1, object2)); ``` Would give us: ``` { "key": "00700916391", "message": { "subject": "Hey what's up?", "from": "example1@example.com", "to": "example2@example.com", "something": "something new" } } ``` Is there an Angular function that already does a deep merge that I am not aware of? If not is there a native way to do this in javascript recursively for n levels deep?

Original source

Related problems