i have an array data like this ..
var array = [{name : 'customer.data.profession.code' , value : 'P001'},
{name : 'customer.data.profession.name', value : 'DRIVER'},
{name : 'customer.data.address', value : '21 Street'},
{name : 'customer.level', value : '1'} ];
i want to serializing that array into single object like below , how can i achieve that ?
let customer = {"data" : {"profession" : {"code" : "P001", "name" : "DRIVER"} ,
"address" : "21 Street"},
"level" : "1"}
CodePudding user response:
Step 1: Convert each item in your array to self object.
From
{
name: 'customer.data.profession.code',
value: 'P001'
}
To
{
"data": {
"profession": {
"code": "P001"
}
}
}
Step 2: Merge all of object to 1 object to get final result by Array.reduce
with an deepMerge
library.
var array = [{
name: 'customer.data.profession.code',
value: 'P001'
},
{
name: 'customer.data.profession.name',
value: 'DRIVER'
},
{
name: 'customer.data.address',
value: '21 Street'
},
{
name: 'customer.level',
value: '1'
}
];
// Convert each item to object
var tempResult = [];
array.forEach(item => {
var keys = item.name.replace('customer.', '').split('.').reverse();
var valueKey = keys.shift();
var obj = {};
obj[valueKey] = item.value;
if (keys.length > 0) {
obj = keys.reduce((acc, key) => {
var newObj = {};
newObj[key] = acc;
return newObj;
}, obj)
}
tempResult.push(obj);
});
// merge object by reduce
var finalResult = tempResult.reduce((acc, item) => {
acc = mergeDeep(item, acc)
return acc
}, {});
console.log(finalResult);
// lib from https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6
function mergeDeep(target, source) {
const isObject = (obj) => obj && typeof obj === 'object';
if (!isObject(target) || !isObject(source)) {
return source;
}
Object.keys(source).forEach(key => {
const targetValue = target[key];
const sourceValue = source[key];
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = targetValue.concat(sourceValue);
} else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = mergeDeep(Object.assign({}, targetValue), sourceValue);
} else {
target[key] = sourceValue;
}
});
return target;
}
CodePudding user response:
A possible approach could be based on a classic map
and reduce
task.
In a 1st step one would map
the array of { name, value }
items into an array where each item features e.g. a keyList
property which was computed from the original item name
's path value ...
console.log(
'map result ...',
[
{ name: 'customer.data.profession.code', value: 'P001' },
{ name: 'customer.data.profession.name', value: 'DRIVER' },
{ name: 'customer.data.address', value: '21 Street' },
{ name: 'customer.level', value: '1' },
]
.map(({ name: keyPath, value }) => ({
// `.slice(1)` gets rid of the `customer` key.
keyList: keyPath.split('.').slice(1),
value,
}))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
The 2nd step would process the above array by two nested reduce
tasks (the first is processing the altered array, the second does process each altered item's keyList
) where one in addition needs to take advantage of object mutation ...
// programmatically builds/aggregates new entries
// by mutating an initially passed reference.
function aggregateReferenceByKeyAndValue({ ref, val }, key, idx, arr) {
return {
// - if entry already exists return it ...
// - ... otherwise initialize and return a new one.
ref: (ref[key] ??= (idx < (arr.length - 1)) ? {} : val),
val,
};
}
const sampleData = [
{ name: 'customer.data.profession.code', value: 'P001' },
{ name: 'customer.data.profession.name', value: 'DRIVER' },
{ name: 'customer.data.address', value: '21 Street' },
{ name: 'customer.level', value: '1' },
];
console.log(
'map and reduce result ...',
sampleData
.map(({ name: keyPath, value }) => ({
keyList: keyPath.split('.').slice(1),
value,
}))
.reduce((result, { keyList, value }) => {
// - do not use the reducer's return value,
// - make use of the `result` mutation instead.
keyList.reduce(aggregateReferenceByKeyAndValue, {
ref: result,
val: value,
});
return result;
}, {}) // the last argument is the to be mutated `result` reference.
);
.as-console-wrapper { min-height: 100%!important; top: 0; }