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);