I have a nested JSON object which is of the format
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2:[{
dataType : 'Object'
},{
value : [{
secondLevelKey1 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey2 : [{
dataType : 'Object'
},{
value : [{
thirdLevelKey1:[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
secondLevelKey3 :[{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
for easier understanding this is an array of objects, in each object, the value of key is again an array of 3 objects, of which first tells the dataType and there is value in the second object, and some other keys in third object.
If the dataType is Object then the second object which has the key property called value will have again array of objects repeating the procedure.
I am able to flatten and the flattened object is like
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
secondLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
but now firstLevelKey2 property name and secondLevelKey2 name are lost
is there a way to store the names so that while mapping back i can know how to nest them back in the same format how i recieved it ? like for example in this format
[{
firstLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey1 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey2 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey2#thirdLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey2#secondLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
},{
firstLevelKey3 : [{
dataType : 'String'
},{
value : 'someString'
},{
someKey : 'someValue'
}]
}]
any help would be very appreciated.Thanks!
CodePudding user response:
You could use a recursive approach here, creating a flattenWithPath
function that takes an array and path as arguments.
By passing the path for each call we can ensure we can retain the object hierarchy in the key names.
const input = [{ firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ firstLevelKey2:[{ dataType : 'Object' },{ value : [{ secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ secondLevelKey2 : [{ dataType : 'Object' },{ value : [{ thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }]
function flattenWithPath(arr, path = []) {
let result = [];
for (let obj of arr) {
const [key, value] = Object.entries(obj)[0];
if (Array.isArray(value[1].value)) {
result.push(...flattenWithPath(value[1].value, [...path, key]));
} else {
result.push({ [[...path, key].join('#')]: value });
}
}
return result;
}
console.log(JSON.stringify(flattenWithPath(input), null, 2))
.as-console-wrapper { max-height: 100% !important; }
CodePudding user response:
Here's another take.
const input = [{ firstLevelKey1 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ firstLevelKey2:[{ dataType : 'Object' },{ value : [{ secondLevelKey1 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ secondLevelKey2 : [{ dataType : 'Object' },{ value : [{ thirdLevelKey1:[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey2 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] },{ thirdLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ secondLevelKey3 :[{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }] },{ someKey : 'someValue' }] },{ firstLevelKey3 : [{ dataType : 'String' },{ value : 'someString' },{ someKey : 'someValue' }] }]
function flatObj(obj, path = []) {
return Object.entries(obj).flatMap(([k, v]) =>
v[0].dataType === 'Object' ?
v[1].value.flatMap(obj => flatObj(obj, [...path, k])) :
[{[[...path, k].join('#')]: v}]
);
}
console.log(input.flatMap(obj => flatObj(obj)));