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);
Dan
  • 2,304
  • 6
  • 42
  • 69
  • 3
    I'd take a look at how Lodash's merge works: https://lodash.com/docs/4.17.15#merge It's recursive and has excellent support for many different data types. – ArrayKnight Oct 23 '19 at 17:15
  • 1
    This has been asked before. Did you try any of the answers in [this](https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge), [this](https://stackoverflow.com/questions/48294734/recursive-merging-of-objects-in-javascript), or [this](https://stackoverflow.com/questions/32792185/how-to-recursively-merge-2-javascript-objects)? – trincot Oct 23 '19 at 17:24

0 Answers0