Home > Software design >  Adding data to a nested JSON object with children based on an array - Javascript/REACT
Adding data to a nested JSON object with children based on an array - Javascript/REACT

Time:11-16

Hello stackoverflow community! I've been creating my own fullstack application for a while now, on the NEXTjs framework. This is going pretty well!! Unfortunately, I got stuck on a JSON import object for a treeview component. The treeview component must be populated using a specific nested structure, along with which treeview item should be selected on an initial render.

I managed to get the correct JSON object from the database, using a sql recursive tree function.

const jsonObject = 

{
    "id": "bfa3fdf8-4672-404e-baf5-0f9098a5705b",
    "label": "main category 1",
    "children": [
        {
            "id": "12e544bc-91b1-4e5d-bdbc-2163a5618305",
            "label": "sub category 1.1",
            "children": []
        },
        {
            "id": "3f5e5cc7-f8b2-4d75-89e1-841c66d863e6",
            "label": "sub category 1.2",
            "children": [
                {
                    "id": "903a727f-d94d-44ff-b2f6-a985fd167343",
                    "label": "sub category 1.2.1",
                    "children": []
                },
                {
                    "id": "fb344480-8588-4ce3-9662-f8e89069e4b4",
                    "label": "sub category 1.2.2",
                    "children": []
                }
            ]
        }
    ]
}

The problem is that this object, with categories needs to be updated with a 'checked: "true"' or 'checked: "false"' key value pair based on the existence in the referenceSelectedCategories array. And I don't know how to do this; maintaining the structure and object as needed.

const desiredOutputJsonObject = 

{
    "id": "bfa3fdf8-4672-404e-baf5-0f9098a5705b",
    "label": "main category 1",
**  "checked": "false",**
    "children": [
        {
            "id": "12e544bc-91b1-4e5d-bdbc-2163a5618305",
            "label": "sub category 1.1",
**          "checked": "true",**
            "children": []
        },
        {
            "id": "3f5e5cc7-f8b2-4d75-89e1-841c66d863e6",
            "label": "sub category 1.2",
**          "checked": "false",**
            "children": [
                {
                    "id": "903a727f-d94d-44ff-b2f6-a985fd167343",
                    "label": "sub category 1.2.1",
**                  "checked": "false",**                    
                    "children": []
                },
                {
                    "id": "fb344480-8588-4ce3-9662-f8e89069e4b4",
                    "label": "sub category 1.2.2",
**                  "checked": "true",**   
                    "children": []
                }
            ]
        }
    ]
}
const referenceSelectedCategories = 
[
    {
        "categoryId": "12e544bc-91b1-4e5d-bdbc-2163a5618305",
        "productId": "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
        "Id": "f82b0f63-3f39-486c-9157-5c7683b8e3b2"
    },
    {
        "categoryId": "fb344480-8588-4ce3-9662-f8e89069e4b4",
        "productId": "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
        "Id": "b2e8681b-eec4-404d-8f87-c6314db42e30"
    }
]

I've read several stackoverflow questions, also searched for examples, but can't get it to work. Could someone help me out here?

Some extra information:

  • Code language I'm using is REACT on NEXTjs framework;
  • Treeview component could have a dept of max 5 levels;
  • The structure of the JSON object doesn't change, it's exactly as presented above.
  • The "id" in the JSON object corresponds to the "categoryId" in the array.
  • Do you need more information? :) Just ask, I'll provide you with the extra details!

Kind Regards,

Chris

CodePudding user response:

A straight forward solution with recursive method. Done a quick test, working fine. If any issues found, please point it out.

const parentObj = 
[
    {
        "categoryId": "12e544bc-91b1-4e5d-bdbc-2163a5618305",
        "productId": "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
        "Id": "f82b0f63-3f39-486c-9157-5c7683b8e3b2"
    },
    {
        "categoryId": "fb344480-8588-4ce3-9662-f8e89069e4b4",
        "productId": "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
        "Id": "b2e8681b-eec4-404d-8f87-c6314db42e30"
    }
]

const existingId = parentObj.map((item)=> (item.Id))

const childobj = 

{
    "id": "bfa3fdf8-4672-404e-baf5-0f9098a5705b",
    "label": "main category 1",
    "children": [
        {
            "id": "12e544bc-91b1-4e5d-bdbc-2163a5618305",
            "label": "sub category 1.1",
            "children": []
        },
        {
            "id": "3f5e5cc7-f8b2-4d75-89e1-841c66d863e6",
            "label": "sub category 1.2",
            "children": [
                {
                    "id": "903a727f-d94d-44ff-b2f6-a985fd167343",
                    "label": "sub category 1.2.1",
                    "children": []
                },
                {
                    "id": "f82b0f63-3f39-486c-9157-5c7683b8e3b2",
                    "label": "sub category 1.2.2",
                    "children": []
                }
            ]
        }
    ]
}
const updateData=(obj)=> {
    if(existingId.includes(obj.id)) obj['checked'] = true; else obj['checked'] = false
}

const traverse=(childObj)=> {
    for(const obj of childObj) {
        updateData(obj);
        if(obj.children.length > 0) traverse(obj.children); 
    }
}

traverse(childObj);

CodePudding user response:

Here you can ty this logic :

let desiredOutputJsonObject = {
  id: "bfa3fdf8-4672-404e-baf5-0f9098a5705b",
  label: "main category 1",
  checked: false,
  children: [
    {
      id: "12e544bc-91b1-4e5d-bdbc-2163a5618305",
      label: "sub category 1.1",
      checked: true,
      children: [],
    },
    {
      id: "3f5e5cc7-f8b2-4d75-89e1-841c66d863e6",
      label: "sub category 1.2",
      checked: false,
      children: [
        {
          id: "903a727f-d94d-44ff-b2f6-a985fd167343",
          label: "sub category 1.2.1",
          checked: false,
          children: [],
        },
        {
          id: "fb344480-8588-4ce3-9662-f8e89069e4b4",
          label: "sub category 1.2.2",
          checked: true,
          children: [
              {
          id: "fb344480-8588-4ce3-9662-f8e89069e4b9",
          label: "sub category 1.2.2",
          checked: false,
          children: [],
        },
          ],
        },
          
      ],
    },
  ],
};

let referenceSelectedCategories = [
  {
    categoryId: "12e544bc-91b1-4e5d-bdbc-2163a5618305",
    productId: "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
    Id: "f82b0f63-3f39-486c-9157-5c7683b8e3b2",
  },
  {
    categoryId: "fb344480-8588-4ce3-9662-f8e89069e4b4",
    productId: "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
    Id: "b2e8681b-eec4-404d-8f87-c6314db42e30",
  },
    {
    categoryId:"fb344480-8588-4ce3-9662-f8e89069e4b9",
    productId: "efed1c38-391b-4b5a-a9f1-91f3faec5f44",
    Id: "b2e8681b-eec4-404d-8f87-c6314db42e30",
  },
];

let stack = [desiredOutputJsonObject];

while (stack.length) {
  let desiredOutput = stack.pop();

  if (desiredOutput.children) {
    desiredOutput.children.forEach((node) => {
     //get node whose id == category id
      let result = referenceSelectedCategories.find(
        (obj) => obj.categoryId === node.id
      );

      //   while traversing if we get referenceSelectedCategories.categoryId ==desiredOutputJsonObject.id
      if (result) {
        node.checked = true;
      }

      // for traverse purpose
      if (node.children.length) {
        stack.push(node);
      }
    });
  }
}

console.log(desiredOutputJsonObject);

  • Related