0

I am currently working on a project and I've written something that will do for what I'm trying to do but isn't perfect. It currently takes in 2 objects and merges them letting the second override the first if there is a property name conflict.

The code looks like this.

function appendObject(start, obj) {
    var newObject = start; 
    for (var propName in obj) {
        if (typeof start[propName] === "object" && typeof obj[propName] === "object") {
            for (var propName2 in obj[propName]) {
                newObject[propName][propName2] = obj[propName][propName2];
            }
        } else {
            newObject[propName] = obj[propName];
        }
    }
    return newObject; 
}

This will go one layer deep. So if there is a flat object as a property it will still be able to handle it. But what if there is a more complex object as a property in this object? I have not been able to figure out a good way to handle any level of complexity.

Perhaps I'm missing something basic and there is an easier way to merge objects like this. The practical application here is we have a 'default' set of properties we need on the json and then some possible initial values and user inputted values.

Any ideas?

David Baxter
  • 215
  • 2
  • 10
  • There are a lot of different answers to that question here: http://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically. Take your pick. – trincot Aug 16 '16 at 00:09
  • Google for "deep merge" or "recursive merge". –  Aug 16 '16 at 08:45

3 Answers3

0

Indeed, there is some complexity to overcome there. Your function as it's written doesn't recursively call itself, which you could begin to do to meet your needs. However, others have already solved this problem for you, if you so desire to use their good work.

I'd check out lodash.merge if you haven't already. Their source should begin to shed light on how you want to do this if you are interested in doing it on your own. JS has some quirks, such as typeof [] === 'object' which may induce some breakage depending on exactly what you are merging. Regardless, merge does what you request.

cdaringe
  • 1,274
  • 2
  • 15
  • 33
  • You are totally correct. I am sorta trying to reinvent the wheel but sadly I must. For security reasons my resources are limited on this one. I don't think those security reasons are well founded but that is not up to me. I need to work with pretty much just vanilla js – David Baxter Aug 17 '16 at 17:19
0

You might probably do as follows by mutating the second object;

var o1 = {a:1,b:2,c:{z:1,y:2,w:6}},
    o2 = {c:{z:3,y:4,x:1},d:5,e:6,a:7};
Object.keys(o1).reduce((o,k) => Object.keys(o).includes(k) ? typeof o1[k] === "object" && typeof o[k] === "object" ? (o[k] = Object.assign({},o1[k],o[k]),o)
                                                                                                                   : o
                                                           : (o[k] = o1[k],o), o2);
console.log(o2);
Redu
  • 25,060
  • 6
  • 56
  • 76
0

I found this answer in another thread and wanted to post in incase someone found this thread first. Its original author is Markus. https://stackoverflow.com/a/383245/3897555

I googled for code to merge object properties and ended up here. However since there wasn't any code for recursive merge I wrote it myself. (Maybe jQuery extend is recursive BTW?) Anyhow, hopefully someone else will find it useful as well.

(Now the code does not use Object.prototype :)

Code

/*
* Recursively merge properties of two objects 
*/
function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      } else {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

An example

o1 = {  a : 1,
        b : 2,
        c : {
          ca : 1,
          cb : 2,
          cc : {
            cca : 100,
            ccb : 200 } } };

o2 = {  a : 10,
        c : {
          ca : 10,
          cb : 20, 
          cc : {
            cca : 101,
            ccb : 202 } } };

o3 = MergeRecursive(o1, o2);

Produces object o3 like

o3 = {  a : 10,
        b : 2,
        c : {
          ca : 10,
          cb : 20,
          cc : { 
            cca : 101,
            ccb : 202 } } };
Community
  • 1
  • 1
David Baxter
  • 215
  • 2
  • 10