Home > Software engineering >  How to convert tree json to nested Object in js
How to convert tree json to nested Object in js

Time:07-08

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)

  • Related