0

I've been pulling my hair out trying to merge two multidimensional object arrays. I have a "default" object array and then a "user defined" object array.

I can, of course, do this in a way that would not make the code reusable. I want something I can, no matter the makeup, pass two object arrays to and have it return a perfect merge.

var defaults = {
    type: 1,
    gui: {
        width: 900,
        height: 600,
        margin: {
            top: 50,
            bottom: 200,
            left: 100,
            right: 50
        },
        mBg: ['#3f4c6b', '#606c88'],
        mBgDir: 'vertical',
        gBg: "#f9f9f9",
        axlCol: '#000000',
        axLw: 1,
        xTitle: "X Title",
        xFsz: 16,
        xFnt: "Arial",
        yTitle: "Y Title",
        yFsz: 16,
        yFnt: "Arial",
        title: "Default Test",
        titFsz: 16,
        titFnt: "Arial",
        labelFnt: "Arial",
        labelSize: 13,
        lblCol: "#ffffff",
        plotLineCol: "#3f4c6b",
        plotLineWidth: 1,
        plotDots: true,
        dotSize: 2,
        dotCol: "#000000",
        dotBorder: "#FF0000",
        dotBrdSize: 0
    }
}

var userdefined = {
        data: 'qdbh',
        ele: 'qgraph',
        gui: {
            xTitle: "Date/Time",
            yTitle: "Testing",
            title: "Last Day by Hour",
        },
        metrics: ['test', 'test1'],
        caldep: []
    }

The result I'm looking for is this:

var result = {
    data: 'qdbh',
    ele: 'qgraph',
    type: 1,
    metrics: ['test', 'test1'],
    caldep: [],
    gui: {
        width: 900,
        height: 600,
        margin: {
            top: 50,
            bottom: 200,
            left: 100,
            right: 50
        },
        xTitle: "Date/Time",
        yTitle: "Testing",
        title: "Last Day by Hour",
        mBg: ['#3f4c6b', '#606c88'],
        mBgDir: 'vertical',
        gBg: "#f9f9f9",
        axlCol: '#000000',
        axLw: 1,
        xFsz: 16,
        xFnt: "Arial",
        yFsz: 16,
        yFnt: "Arial",
        titFsz: 16,
        titFnt: "Arial",
        labelFnt: "Arial",
        labelSize: 13,
        lblCol: "#ffffff",
        plotLineCol: "#3f4c6b",
        plotLineWidth: 1,
        plotDots: true,
        dotSize: 2,
        dotCol: "#000000",
        dotBorder: "#FF0000",
        dotBrdSize: 0
    }
}

I can also do this if I include ALL available keys in the defaults list. As you can see a few of the user defined keys don't appear in the defaults at all, as they really have to be user defined.

I feel I'm close but no cigar quite yet. I can move forward by including ALL keys in defaults, it works. However, I'd like a better solution if possible.

This is what I have so far:

function getObjectKeys(obj) {
    return Object.keys(obj);
}

function getObjectArrayType(obj) {
    var type = Object.prototype.toString.call(obj);
    if(type === "[object Object]") {
        return "object";
    } else if(type === "[object Array]") {
        return "array";
    } else {
        return "unknown";
    }
}

function mergeJsonObj(defaults, destination) {    
    var defKeys = getObjectKeys(defaults);
    var result = {};
    for (var d = 0; d < defKeys.length; d++) { //loop through object keys

         //does default key exist in destination
        if (destination[defKeys[d]] !== undefined) { //YES

            //Is key an object
            if (getObjectArrayType(destination[defKeys[d]]) === "object") { //YES
                result[defKeys[d]] = mergeJsonObj(defaults[defKeys[d]], destination[defKeys[d]]);
            } else {
                result[defKeys[d]] = destination[defKeys[d]];
            }
        } else { //NO
            result[defKeys[d]] = defaults[defKeys[d]]; //add default to graph spec
        }
    }
    return result;
}

mergeJsonObj(defaults, userdefined);
2
  • 3
    I'd take a look at how Lodash's merge works: lodash.com/docs/4.17.15#merge It's recursive and has excellent support for many different data types. Commented Oct 23, 2019 at 17:15
  • 1
    This has been asked before. Did you try any of the answers in this, this, or this? Commented Oct 23, 2019 at 17:24

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.