We have two objects of same structure where we want to combine values selectively based on element name. Some we want to accept the update value and overwrite, others we want to ignore the update, and some elements which are arrays we want to combine as a union.
For example, for these two objects..
var server = {
'title': 'string',
'systems': [3,4,5],
'views': 1000,
'authors': ['fred','bill']
};
var update = {
'title': 'new string',
'systems': [5],
'views': 900,
'authors': ['fred','jim']
};
We want to replace title, replace systems, ignore views, and union authors .. producing this object:
var result = {
'title': 'new string', // value repaced
'systems': [5], // array wholly replaced
'views': 1000, // update value ignored
'authors': ['fred','bill','jim'] // update unioned with server
};
We've tried both _.merge and _.assign but they give the wrong results (e.g. systems becomes [5,4,5]) and neither provide the option of ignoring a specific element for update (e.g. views)
There may be more elements added in the future (elsewhere in the code) so we don't want to custom code the combining but instead rely on a default _.assign-like or _.merge-like behaviour for unknown elements.
Is there a lodash function that can handle this?
I don't know if it's possible using lodash, but here is the plain javascript function that will help you to do that:
const server = {
'title': 'string',
'systems': [3,4,5],
'views': 1000,
'authors': ['fred','bill']
};
const update = {
'title': 'new string',
'systems': [5],
'views': 900,
'authors': ['fred','jim']
};
const merge = (source, update, actions) => Object.keys(source).reduce((result, k) => {
if (actions.replace.includes(k)) {
result[k] = update[k];
} else if (actions.ignore.includes(k)) {
result[k] = source[k];
} else if (actions.union.includes(k)) {
result[k] = [...new Set([...source[k], ...update[k]])];
}
return result;
}, {});
console.log(merge(server, update, {replace: ['title', 'systems'], ignore: ['views'], union: ['authors']}));
Where actions is an object of type:
{replace: [<properties to replace>], ignore: [<properties to ignore>], union: [<properties to union>]}