3
const obj1 = {
    prop1: 'value1',
    prop2: 'value2',
    prop3: { prop4: 'value4', prop5: {
         prop5: 'value5'
         } 
    },
}
const obj2 = {
    prop6: 'value6',
    prop2: 'value2',
    prop7: { prop8: 'value8', prop9: {
         prop10: 'value10'
         } 
    },
}

I have these two very nested objects in javascript, and I want to merge them into just one object. Some object property is identical, but some are not; I want to merge them, so the identical ones stay. how do I merge these two deeply nested objects?

Cyrus Raoufi
  • 526
  • 1
  • 3
  • 27

3 Answers3

2

Regarding merging, we generally have two approaches, Shallow merge and Deep Merge. For shallow merge, javascript has these ways.

  1. Object.assign()
  2. Merging via spread operator

But if you want to deep merge, you should iterate through all items of an object and merge them one by one (Merging Recursively) or use some great library like Lodash

  1. Sample of Deep Merging with Lodash
  2. How to Deep Merge JavaScript Objects?
Cyrus Raoufi
  • 526
  • 1
  • 3
  • 27
0

If anyone wish to merge two Object into just one object without using any Library like Lodash then you can do it as like below

function deepMergeObjects(obj1, obj2) {
    const result = {};

    for (const key in obj2) {
        if (obj2.hasOwnProperty(key)) {
            if (typeof obj2[key] === "object" && obj1.hasOwnProperty(key) && typeof obj1[key] === "object") {
                result[key] = deepMergeObjects(obj1[key], obj2[key]);
            } else {
                result[key] = obj2[key];
            }
        }
    }

    for (const key in obj1) {
        if (obj1.hasOwnProperty(key) && !result.hasOwnProperty(key)) {
            if (typeof obj1[key] === "object") {
                result[key] = deepMergeObjects(obj1[key], {});
            } else {
                result[key] = obj1[key];
            }
        }
    }

    return result;
}


const obj1 = {
    a: 1,
    b: {
        c: 2,
        d: 3,
    },
    test1: null,
    test2: {},
    test3: {},
    test4: false,
    test5: undefined
};

const obj2 = {
    b: {
        d: 4,
        e: 5,
    },
    f: 6,
    test1: {},
    test2: null,
    test3: false,
    test4: {},
    test5: {}
};

console.time("time");
const mergedObject = deepMergeObjects(obj1, obj2);
console.timeEnd("time");
console.log(JSON.stringify(mergedObject));

additionally If anyone need to override or add the values of obj1 into obj2 then you can do it as like below way

Method 1:- override or add the values of obj1 into obj2 using ForLoop

function deepMergeObjects(obj1, obj2) {
    for (const key in obj1) {
        if (obj1.hasOwnProperty(key)) {
            if (typeof obj1[key] === "object") {
                if (typeof obj2[key] !== "object" || Array.isArray(obj2[key])) {
                    obj2[key] = Array.isArray(obj1[key]) ? [] : {};
                }
                deepMergeObjects(obj1[key], obj2[key]);
            } else {
                obj2[key] = obj1[key];
            }
        }
    }
}

const obj1 = {
    a: 1,
    b: {
        c: 2,
        d: 3,
    },
    test1: null,
    test2: {},
    test3: {},
    test4: false,
    test5: undefined
};

const obj2 = {
    b: {
        d: 4,
        e: 5,
    },
    f: 6,
    test1: {},
    test2: null,
    test3: false,
    test4: {},
    test5: {}
};

console.time("time");
deepMergeObjects(obj1, obj2);
console.timeEnd("time");
console.log(JSON.stringify(obj2));

Method 2:- override or add the values of obj1 into obj2 using recursively Set Object

const deepMerge = (a, b, fn) =>
  [...new Set([...Object.keys(a), ...Object.keys(b)])].reduce((acc, key) => {
    if (a.hasOwnProperty(key) && b.hasOwnProperty(key)) {
      if (a[key] === null || a[key] === undefined) {
        acc[key] = b[key];
      } else if (b[key] === null || b[key] === undefined) {
        acc[key] = a[key];
      } else if (typeof a[key] === "object" && typeof b[key] === "object") {
        acc[key] = deepMerge(a[key], b[key], fn);
      } else {
        acc[key] = fn(key, a[key], b[key]);
      }
    } else if (a.hasOwnProperty(key)) {
      acc[key] = a[key];
    } else {
      acc[key] = b[key];
    }
    return acc;
  }, {});


const obj1 = {
    a: 1,
    b: {
        c: 2,
        d: 3,
    },
    test1: null,
    test2: {},
    test3: {},
    test4: false,
    test5: undefined
};

const obj2 = {
    b: {
        d: 4,
        e: 5,
    },
    f: 6,
    test1: {},
    test2: null,
    test3: false,
    test4: {},
    test5: {}
};

console.time("time");
const mergedObject = deepMerge(obj1, obj2, (key, a, b) => {
  if (typeof a === "object") {
    return Array.isArray(a) ? [] : {};
  } else {
    return b;
  }
});
console.timeEnd("time");

console.log(JSON.stringify(mergedObject));

I hope this one helps to You

Happy Coding :)

Harsh Patel
  • 1,032
  • 6
  • 21
-1

Recursive merge for array and object

const obj1 = {
  prop1: 'value1',
  prop2: 'value2',
  prop3: {
    prop4: 'value4',
    prop5: {
      prop5: 'value5'
    },
    a: ['a', 'b']
  },
}

const obj2 = {
  prop6: 'value6',
  prop2: 'value2',
  prop7: {
    prop8: 'value8',
    prop9: {
      prop10: 'value10'
    }
  },
  prop3: {
    prop9: 'value9',
    prop8: {
      prop7: 'value7',
      prop8: {
        prop7: 'value7'
      }
    },
    a: ['a', 'b']
  },
}


const Merge = (object1, object2) => {
  if (Array.isArray(object2)) {
    return [...object1, ...object2]
  } else {
    return Object.entries(object2).reduce((acc, [key, value]) => {
      if (
        Object.keys(acc).includes(key) &&
        typeof value === 'object'
      ) {
        acc[key] = Merge(acc[key], value)
      } else {
        acc[key] = value
      }
      
      return acc
    }, { ...object1 })
  }
}

const result = Merge(obj1, obj2)

console.log(result)
kennarddh
  • 2,186
  • 2
  • 6
  • 21