I converted a nested object into tree JSON format but now I need to convert it back to a nested object I tried so many ways but not working as expected. while converting nested object JSON I used recursion to achieve but here is how to operate it with the object.
I really appreciate your help, Thanks
input :
[
{
"name": "DI",
"children": [
{
"name": "t",
"children": [
{
"name": "tID",
"ir": true,
"is": false
},
{
"name": "tTime",
"ir": false,
"is": false
}
],
"ir": false,
"is": false
},
{
"name": "i",
"children": [
{
"name": "idu",
"ir": false,
"is": false
},
{
"name": "il",
"ir": false,
"is": false
},
{
"name": "ibId",
"children": [
{
"name": "ib1",
"ir": false,
"is": false
},
{
"name": "ib2",
"ir": false,
"is": false
}
],
"ir": false,
"is": false
}
],
"ir": false,
"is": false
}
]
}
]
expected o/p:
{
"DI":{
"t":{
"tID":{
"ir":true,
"is":false
},
"tTime":{
"ir":false,
"is":false
},
"ir":false,
"is":false
},
"i":{
"idu":{
"ir":false,
"ir":false
},
"il":{
"ir":false,
"is":false
},
"ibId":{
"ib1":{
"ir":false,
"is":false
},
"ib2":{
"ir":false,
"is":false
},
"ir":false,
"is":false
},
"ir":false,
"is":false
}
}
}
CodePudding user response:
You can use this recursive function:
const toObject = (arr) =>
Object.assign(...arr.map(({name, children, ...rest}) =>
({ [name]: Object.assign(rest, children && toObject(children)) })
));
// Example run:
const input =[{"name": "DI","children": [{"name": "t","children": [{"name": "tID","ir": true,"is": false},{"name": "tTime","ir": false,"is": false}],"ir": false,"is": false},{"name": "i","idx": 0,"children": [{"name": "idu","ir": false,"is": false},{"name": "il","ir": false,"is": false},{"name": "ibId","children": [{"name": "ib1","ir": false,"is": false},{"name": "ib2","ir": false,"is": false}],"ir": false,"is": false}],"ir": false,"is": false}]}];
const result = toObject(input);
console.log(result);
Explanation
arr.map
will iterate over the given array and return an array of the same length by applying a callback to each element. The callback takes an object as argument and immediately assigns some properties to local variables: ({name, children, ...rest})
. rest
will be a copy of the original object, but without the name
and children
properties, which have been captured in separate variables.
The callback then returns an object. The parentheses around that object are needed to make clear that the opening brace belongs to an object literal, and not a statement block.
[name] :
creates a property in that new object, that has a dynamically determined name (look up computed property names). This new object gets the value of rest
which maybe gets extended with more, and that is why Object.assign(rest)
is called.
If there is no children
property in the original object, then the expression children &&
will be undefined, and then Object.assign
will just evaluate to rest
without any mutation, but if children
is an array, then children && toObject(children)
will make the recursive call and return the corresponding object. In that case Object.assign
will merge that object into rest
so the properties are combined into one object.
So, the object returned by Object.assign
is rest
with possibly some nested objects coming from recursion. This object becomes the value of the dynamic [name]
property.
Finally, that arr.map
will thus return these new objects, and they each become separate arguments to the outer call of Object.assign
because of the spread syntax (...
). This will merge all those "little" objects into one combined object, which is returned to the caller.
CodePudding user response:
const input = '[ { "name": "DI", "children": [ { "name": "t", "children": [ { "name": "tID", "ir": true, "is": false }, { "name": "tTime", "ir": false, "is": false } ], "ir": false, "is": false }, { "name": "i", "idx": 0, "children": [ { "name": "idu", "ir": false, "is": false }, { "name": "il", "ir": false, "is": false }, { "name": "ibId", "children": [ { "name": "ib1", "ir": false, "is": false }, { "name": "ib2", "ir": false, "is": false } ], "ir": false, "is": false } ], "ir": false, "is": false } ] } ]'
// console.log(JSON.parse(input))
const convertToObject = (data) => {
const { name, children, ...others } = data
if(!children) return others;
return children.reduce((acc, d) => {
acc[d['name']] = convertToObject(d);
return acc;
}, {})
}
console.log(convertToObject({ 'children': JSON.parse(input) }))
CodePudding user response:
You should use recursion, as others pointed. I'm adding another variation of this solution
const input = [ { "name": "DI", "children": [ { "name": "t", "children": [ { "name": "tID", "ir": true, "is": false }, { "name": "tTime", "ir": false, "is": false } ], "ir": false, "is": false }, { "name": "i", "idx": 0, "children": [ { "name": "idu", "ir": false, "is": false }, { "name": "il", "ir": false, "is": false }, { "name": "ibId", "children": [ { "name": "ib1", "ir": false, "is": false }, { "name": "ib2", "ir": false, "is": false } ], "ir": false, "is": false } ], "ir": false, "is": false } ] } ]
const finalObj = {}
function constructObj(arr, finalObj) {
for (let obj of arr) {
if (obj.name) {
finalObj[obj.name] = {}
if (obj.ir != null) {
finalObj[obj.name].ir = obj.ir
}
if (obj.is != null) {
finalObj[obj.name].is = obj.is
}
if (obj.children)
constructObj(obj.children, finalObj[obj.name])
}
}
}
constructObj(input, finalObj)
console.log(finalObj)
CodePudding user response:
You can use recursive to convert, same as :
const input = [{
"name": "DI",
"children": [{
"name": "t",
"children": [{
"name": "tID",
"ir": true,
"is": false
},
{
"name": "tTime",
"ir": false,
"is": false
}
],
"ir": false,
"is": false
},
{
"name": "i",
"children": [{
"name": "idu",
"ir": false,
"is": false
},
{
"name": "il",
"ir": false,
"is": false
},
{
"name": "ibId",
"children": [{
"name": "ib1",
"ir": false,
"is": false
},
{
"name": "ib2",
"ir": false,
"is": false
}
],
"ir": false,
"is": false
}
],
"ir": false,
"is": false
}
]
}]
const convertToObj = arr => {
return arr.reduce((res, {name, children, ...rest}) => {
res[name] = Object.assign(children ? convertToObj(children) : {}, rest )
return {...res}
}, {})
}
const result = convertToObj(input)
console.log(result)