I have two objects, obj1 = {key1: value1, key2: {key2_1: value2_1, key2_2: value2_2}} is for default values and obj2 = {key2: {key2_2: new_value2_2}} is for altered values (these come from config defaults and a parsed config file)
I want to combine these into one object where any value in obj2 replaces that in obj1 so long as it's not replacing an object, just a singular value. With the example above this would give obj1 = {key1: value1, key2: {key2_1: value2_1, key2_2: new_value2_2}}.
I've tried using the spread operator (...) but that ends up replacing the whole of key2 and essentially removing key2_1 in this case.
Any help would be very nice thanks
You could merge all values and check the inner object and merge these separately.
const
merge = (a, b) => [a, b].reduce((r, o) => Object
.entries(o)
.reduce((q, [k, v]) => ({
...q,
[k]: v && typeof v === 'object' ? merge(q[k] || {}, v) : v
}), r),
{}),
obj1 = { key1: 'value1', key2: { key2_1: 'value2_1', key2_2: 'value2_2' } },
obj2 = { key2: { key2_2: 'new_value2_2' } },
result = merge(obj1, obj2);
console.log(result);
You could create a function that will recursively merge properties of the two objects.
Properties of obj2 will take priority over obj1 and child objects will be merged key by key.
let obj1 = {key1: 'value1', key2: {key2_1: 'value2_1', key2_2: 'value2_2'}}
let obj2 = {key2: {key2_2: 'new_value2_2'}}
function merge(obj1, obj2) {
const result = {};
const combined = { ...obj1, ...obj2 };
for(let k in combined) {
if (combined[k] && (typeof(combined[k]) === 'object')) {
result[k] = merge(obj1[k], obj2[k]);
} else {
result[k] = obj2 ? obj2[k] || obj1[k] : obj1[k]
}
}
return result;
}
console.log('Merged objects:', merge(obj1, obj2))
.as-console-wrapper { max-height: 100% !important; }
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