0

I have json data that looks like this:


{
"domain": {
     "id": "40d74976-5db2-4a57-2a62-08d80969933d",
      "name": "A",
      "categories": {
        "items": [
          {
            "id": "b17e674a-b64d-4224-bf93-016bc07b6349",
            "name": "Category A",
            "path": "A/Category A"
          },
          {
            "id": "f6490fe4-98b0-4918-a419-0177000227c2",
            "name": "Category AA",
            "path": "A/Category A/Category AA"
          },
          {
            "id": "092163a5-b96f-4453-8a22-0307c1f1abec",
            "name": "Category B",
            "path": "A/Category B"
          },
          {
            "id": "78ac6a08-4dc4-4f60-b0fd-0411b9631c4a",
            "name": "Category B-2",
            "path": "A/Category B/Category B-2"
          }
        ]
      }
   }
}

And i would like the result to be this:

{
"domain": {
      "id" : "40d74976-5db2-4a57-2a62-08d80969933d",
      "name": "A",
      "categories": {
        "items": [
          {
            "id": "b17e674a-b64d-4224-bf93-016bc07b6349",
            "name": "Category A",
            "path": "A/Category A"
            "children": [
                 {
                  "id": "f6490fe4-98b0-4918-a419-0177000227c2",
                  "name": "Category AA",
                  "path": "A/Category A/Category AA"
                  }
              ]
          },
          {
            "id": "092163a5-b96f-4453-8a22-0307c1f1abec",
            "name": "Category B",
            "path": "Domain A/Category B"
            "children" :[
                        {
                         "id": "78ac6a08-4dc4-4f60-b0fd-0411b9631c4a",
                         "name": "Category B-2",
                         "path": "A/Category B/Category B-2"
                        }
             ]
          }
        ]
      }
   }
}

I need to convert the json data in this way because i want to display this in the treeview format on my vue application but also retain the original id of each element since i want to implement the feature allow adding children to each specific element if the user needs to. To do that, it would need the original path of that element and the id of the element to which the child is being added

Pooja Arya
  • 121
  • 1
  • 11
  • That is not valid JSON. It cannot start with `"domain": {`. Braces missing? – trincot Jul 06 '20 at 19:52
  • Do you have some code that you've tried that you need help with? Otherwise, the answers here might help: https://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript – mlibby Jul 06 '20 at 19:54
  • Habe you already tried something? – Benjamin Eckardt Jul 06 '20 at 19:56
  • Is there a reason why in the desired output you want the top level to have its children via "categories.items", and all the other levels via "children"? Seems to complicate working with it... – trincot Jul 06 '20 at 20:03
  • hi, i am sorry for missing the braces at the start of the json but it is just a typo in my question. my code for json is correct and does have braces. – Pooja Arya Jul 06 '20 at 20:26
  • @trincot i need to maintain the domain value as the top level and have its children via categories.items because in my json i have multiple such domains which further have categories and i need to display the categories treeview on UI based on domain that the user will select. Does this answer your question? – Pooja Arya Jul 06 '20 at 20:41
  • So, does `categories` have any other properties than `items`? – trincot Jul 06 '20 at 20:55
  • @trincot yes categories will have page properties apart from items like hasNextPage, hasPreviousPage, totalPages – Pooja Arya Jul 06 '20 at 20:58
  • OK, I see. It makes sense. – trincot Jul 06 '20 at 20:58

1 Answers1

1

You can use a Map to key (a copy of) your items by their path attribute, and then iterate the items to link each of them with the parent (via lookup in the map). Finally structure the top-level of the desired output.

Here is how that could be done:

let data = {"domain": {"id": "40d74976-5db2-4a57-2a62-08d80969933d","name": "A","categories": {"items": [{"id": "b17e674a-b64d-4224-bf93-016bc07b6349","name": "Category A","path": "A/Category A"},{"id": "f6490fe4-98b0-4918-a419-0177000227c2","name": "Category AA","path": "A/Category A/Category AA"},{"id": "092163a5-b96f-4453-8a22-0307c1f1abec","name": "Category B","path": "A/Category B"},{"id": "78ac6a08-4dc4-4f60-b0fd-0411b9631c4a","name": "Category B-2","path": "A/Category B/Category B-2"}]}}};
   
let root = {};
let { id, name, categories: { items } } = data.domain; 
let map = new Map(items.map(o => [o.path, {...o}])).set(name, root);
items.forEach(o => {
    let parent = map.get(o.path.slice(0, -o.name.length-1));
    parent.children = (parent.children || []).concat(map.get(o.path));
});
let result = { id, name, categories: { items: root.children } };

console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286