2

I have an array of objects which want to convert it to JSON tree structure by java script function and then use it in a vue js project. The page have a vuetify tree component which need JSON tree structure. My data have been stored in MySql table with parent child structure.

Sample Date :

[
    {"id": 123, "parentid": 0, "name": "Mammals"},
    {"id": 456, "parentid": 123, "name": "Dogs"},
    {"id": 214, "parentid": 456, "name": "Labradors"},
    {"id": 810, "parentid": 456, "name": "Pugs"},
    {"id": 919, "parentid": 456, "name": "Terriers"}
]

Result :

[
    {
        "id": 123,
        "parentid": 0,
        "name": "Mammals",
        "children": [
            {
                "id": 456,
                "parentid": 123,
                "name": "Dogs",
                "children": [
                    {
                        "id": 214,
                        "parentid": 456,
                        "name": "Labradors"
                    },
                    {
                        "id": 810,
                        "parentid": 456,
                        "name": "Pugs"
                    },
                    {
                        "id": 919,
                        "parentid": 456,
                        "name": "Terriers"
                    }
                ]
            }
        ]
    }
]

Sample data from this address: https://gist.github.com/smrchy/7040377

2 Answers 2

3

You can perform a reduce operation on the array using an object to store the references to each object (for adding children to) and an array to store the result.

const arr = [
    {"id": 123, "parentid": 0, "name": "Mammals"},
    {"id": 456, "parentid": 123, "name": "Dogs"},
    {"id": 214, "parentid": 456, "name": "Labradors"},
    {"id": 810, "parentid": 456, "name": "Pugs"},
    {"id": 919, "parentid": 456, "name": "Terriers"}
];
const {res} = arr.reduce((acc,curr)=>{
  if(acc.parentMap[curr.parentid]){
    (acc.parentMap[curr.parentid].children = 
           acc.parentMap[curr.parentid].children || []).push(curr);
  } else {
    acc.res.push(curr);
  }
  acc.parentMap[curr.id] = curr;
  return acc;
}, {parentMap: {}, res: []});
console.log(res);

Sign up to request clarification or add additional context in comments.

Comments

0

@unmitigated 's response only works if your list is pre-ordered.

Instead, inspired heavily from @alexandru.pausan in Build tree array from flat array in javascript.

I find it easier to understand to:

  • create an object/dictionary of all possible ids in the array, and
  • then go through the dictionary once attaching children to parents:
  const array = [
      { id: 919, parentid: 456, name: "Terriers" },
      { id: 456, parentid: 123, name: "Dogs" },
      { id: 214, parentid: 456, name: "Labradors" },
      { id: 810, parentid: 456, name: "Pugs" },
      { id: 123, parentid: 0, name: "Mammals" },
    ];
    
    let tree = [], arrayDictionary = {};
    
    // First map the nodes of the array to an object/dictionary where the key is their id
    array.forEach((cat) => {
      arrayDictionary[cat.id] = cat;
      arrayDictionary[cat.id]["children"] = [];
    });
    
    
    // for each entry in the dictionary
    for (var entry in arrayDictionary) {

      // get all the data for this entry in the dictionary
      const mappedElem = arrayDictionary[entry];

      // if the element has a parent, add it
      if (
        mappedElem.parentid && // the dictionary has a parent
        arrayDictionary[mappedElem["parentid"]] // and that parent exists
        ) {

        arrayDictionary[mappedElem["parentid"]]["children"].push(mappedElem);
      }
      // else is at the root level (parentid = null or 0)
      else {
        tree.push(mappedElem);
      }
    }
    
    console.log(tree);

 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.