adding two objects without overriding keys within the objects Javascript

i have two objects, a master and a temp the master looks like

{
    "gnome":{
        "child":{
            name:"child",
            race:"gnome"
        },
        "youngling":{
            name:"youngling",
            race:"gnome"
        }
    },
    "human":{...},
    ...
}

and the temp looks like

{
    "gnome":{
        "man":{
            name:"man",
            race:"gnome"
        }
}

what i am trying to do is have the temp be added to the master like

{
    "gnome":{
        "child":{...},
        "youngling":{...},
        "man":{...}
    },
    "human":{...},
    ...
}

what i currently have

let obj = {}
function generateJson() {
        let race = getinput("race").value
        let name = getinput("name").value


        let temp = {}
        temp[`${race}`] = {}
        temp[`${race}`][`${name}`] = {
            name: name,
            race: race
        }

        obj = Object.assign(obj, temp)
}

all it does is empties and override the first duplicate key with the temp value a.e. {gnome:{man:{..}}}

earlier this question was closed because it should have been awnsered with How can I merge properties of two JavaScript objects dynamically? which sadly it didn’t, all of the solutions override objects within objects, i want to add to similar keys

Answer

Chris Ferdinandi wrote a helper for this here;

I’ve added an updated version below, but wanted to add a fix for my biggest frustration with Object.assign.

It mutates the source material. To fix this, you can add an empty object as the first argument of the deepAssign function, or use function copyDeepAssign below.

// mutates the source material
function deepAssign(...args) {

    // Make sure there are objects to merge
    const len = args.length;
    if (len < 1) return;
    
    const main = args[0];
    if (len < 2) return main

    // Merge all objects into first
    let i = 0,
        curr;
    while (i < len) {
        curr = args[i];
        for (var key in curr) {
            // If it's an object, recursively merge
            // Otherwise, push to key
            if (Object.prototype.toString.call(curr[key]) === '[object Object]') {
                main[key] = deepAssign(main[key] || {}, curr[key]);
            } else {
                main[key] = curr[key];
            }
        }
        i++;
    }

    return main;
}

// Doesn't mutate the source material
function copyDeepAssign(...args) {
    const base = {};
    
    return deepAssign(base, ...args);
}

Leave a Reply

Your email address will not be published. Required fields are marked *