Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Recursive" spread operator in JS for objects

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

like image 838
nxe Avatar asked Nov 18 '25 17:11

nxe


2 Answers

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);
like image 187
Nina Scholz Avatar answered Nov 21 '25 07:11

Nina Scholz


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; }
like image 41
Terry Lennox Avatar answered Nov 21 '25 06:11

Terry Lennox



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!