Home > Enterprise >  How to Filter a Complex JSON Structure?
How to Filter a Complex JSON Structure?

Time:09-29

I have the following JSON data:

{
  "data": {
    "event": {
      "eventId": "599df9a8-efdd-440f-936b-a4cab9100988",
      "name": "abc",
      "eventOrder": {
        "menuItemIds": [
          {
            "menuId": "130c4d6a-ba3c-43fc-917c-17090b26a36e",
            "menuItemId": "422ec16c-c9c0-4c3d-a974-021dab39e563",
            "quantity": 5
          },
          {
            "menuId": "de6368d5-a076-4058-8f93-a0bac39bb451",
            "menuItemId": "945dafd8-bf01-4a51-b6c8-a4c863db5d1f",
            "quantity": 4
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "c042f13b-b49f-4164-8817-c6a9623c7c40",
            "quantity": 6
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",
            "quantity": 2
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "a6697045-5c3d-4473-a434-c0674b8f4af2",
            "quantity": 1
          }
        ],
        "menus": [
          {
            "menuId": "de6368d5-a076-4058-8f93-a0bac39bb451",
            "name": "Canapé Two",
            "category": "FOOD",
            "menuSections": [
              {
                "name": "Package ",
                "menuSectionItems": [
                  {
                    "itemId": "945dafd8-bf01-4a51-b6c8-a4c863db5d1f",
                    "name": "Canapé Two"
                  }
                ]
              }
            ]
          },
          {
            "menuId": "130c4d6a-ba3c-43fc-917c-17090b26a36e",
            "name": "Canapé One ",
            "category": "FOOD",
            "menuSections": [
              {
                "name": "Package ",
                "menuSectionItems": [
                  {
                    "itemId": "422ec16c-c9c0-4c3d-a974-021dab39e563",
                    "name": "Canapé One "
                  }
                ]
              }
            ]
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "name": "Package Two ",
            "category": "DRINK",
            "menuSections": [
              {
                "name": "Packages ",
                "menuSectionItems": [
                  {
                    "itemId": "c042f13b-b49f-4164-8817-c6a9623c7c40",
                    "name": "Package Two - 2 Hours "
                  },
                  {
                    "itemId": "1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",
                    "name": "Package Two - 3 Hours "
                  },
                  {
                    "itemId": "a6697045-5c3d-4473-a434-c0674b8f4af2",
                    "name": "Package Two - 4 Hours "
                  }
                ]
              }
            ]
          }
        ]
      }
    }
  }
}

The JSON represents a food / drinks menu.

menus is an array of objects that contains all menus, let's take the first object as an example. The name of the menu is Canape Two and it's under a section named Package, the section name exists under menuSections and one menu might exist under multiple section.

menuSectionItems also contain a list of menu items inside a menu, and that might also contain sub items itself.

We also have menuItemIds which contains the quantity of an item in the menu.

What I'm trying to do is to display the data in the following form:

* SECTION NAME
    * MENU NAME
        * ITEM NAME    QTY: X
            * SUB-ITEM NAME

Based on the JSON I provided above, the result should be:

* Package
    * Canape Two
        * Canape Two    QTY: 4
            * (No Sub-Item, So Blank)
    * Canape One
        * Canape One    QTY: 5
            * (No Sub-Item, So Blank)

* Packages
    * Package Two
        * Package Two - 2 Hours    QTY: 6
            * (No Sub-Item, So Blank)
        * Package Two - 3 Hours    QTY: 2
            * (No Sub-Item, So Blank)
        * Package Two - 4 Hours    QTY: 1
            * (No Sub-Item, So Blank)

I have no idea on how to filter the data, and I would be very happy to get your help. I am also going to use React to render the data as a list to the user interface.

CodePudding user response:

Assuming the menuSections array always contains one element only, you could start splitting your data in two arrays:

  • menuItemIds
  • menu

Then, for each id in menuItemIds you can use find() on the menus array to get the menu element and the menuItem element.

Once you got all that, you can build a result object formatted according to your requirements:

const data = {
  "data": {
    "event": {
      "eventId": "599df9a8-efdd-440f-936b-a4cab9100988",
      "name": "abc",
      "eventOrder": {
        "menuItemIds": [{
            "menuId": "130c4d6a-ba3c-43fc-917c-17090b26a36e",
            "menuItemId": "422ec16c-c9c0-4c3d-a974-021dab39e563",
            "quantity": 5
          },
          {
            "menuId": "de6368d5-a076-4058-8f93-a0bac39bb451",
            "menuItemId": "945dafd8-bf01-4a51-b6c8-a4c863db5d1f",
            "quantity": 4
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "c042f13b-b49f-4164-8817-c6a9623c7c40",
            "quantity": 6
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",
            "quantity": 2
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "menuItemId": "a6697045-5c3d-4473-a434-c0674b8f4af2",
            "quantity": 1
          }
        ],
        "menus": [{
            "menuId": "de6368d5-a076-4058-8f93-a0bac39bb451",
            "name": "Canapé Two",
            "category": "FOOD",
            "menuSections": [{
              "name": "Package ",
              "menuSectionItems": [{
                "itemId": "945dafd8-bf01-4a51-b6c8-a4c863db5d1f",
                "name": "Canapé Two"
              }]
            }]
          },
          {
            "menuId": "130c4d6a-ba3c-43fc-917c-17090b26a36e",
            "name": "Canapé One ",
            "category": "FOOD",
            "menuSections": [{
              "name": "Package ",
              "menuSectionItems": [{
                "itemId": "422ec16c-c9c0-4c3d-a974-021dab39e563",
                "name": "Canapé One "
              }]
            }]
          },
          {
            "menuId": "966a7ec0-5ef4-4514-bd10-0043fbca982c",
            "name": "Package Two ",
            "category": "DRINK",
            "menuSections": [{
              "name": "Packages ",
              "menuSectionItems": [{
                  "itemId": "c042f13b-b49f-4164-8817-c6a9623c7c40",
                  "name": "Package Two - 2 Hours "
                },
                {
                  "itemId": "1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",
                  "name": "Package Two - 3 Hours "
                },
                {
                  "itemId": "a6697045-5c3d-4473-a434-c0674b8f4af2",
                  "name": "Package Two - 4 Hours "
                }
              ]
            }]
          }
        ]
      }
    }
  }
}


const menuItemIds = data.data.event.eventOrder.menuItemIds
const menus = data.data.event.eventOrder.menus

const resObj = {}

for (const item of menuItemIds) {
  const menuId = item.menuId
  const menuItemId = item.menuItemId
  const quantity = item.quantity

  const theMenu = menus.find(m => m.menuId === menuId)

  const theSectionItem = theMenu.menuSections[0].menuSectionItems.find(m => m.itemId === menuItemId)

  if (resObj.hasOwnProperty(theMenu.menuSections[0].name)) {
    resObj[theMenu.menuSections[0].name].push({
      menuName: theMenu.name,
      menuSectionItemName: theSectionItem.name,
      menuSectionItemQty: quantity
    })
  } else {
    resObj[theMenu.menuSections[0].name] = []
    resObj[theMenu.menuSections[0].name].push({
      menuName: theMenu.name,
      menuSectionItemName: theSectionItem.name,
      menuSectionItemQty: quantity
    })
  }
}

console.log(resObj)

CodePudding user response:

Let's leave out sub-items for the moment until you give an example. Then all this is left is to group by section, menu, and item.

In order to print that as list we'll re-use something.

var input = {data:{event:{eventId:"599df9a8-efdd-440f-936b-a4cab9100988",name:"abc",eventOrder:{menuItemIds:[{menuId:"130c4d6a-ba3c-43fc-917c-17090b26a36e",menuItemId:"422ec16c-c9c0-4c3d-a974-021dab39e563",quantity:5},{menuId:"de6368d5-a076-4058-8f93-a0bac39bb451",menuItemId:"945dafd8-bf01-4a51-b6c8-a4c863db5d1f",quantity:4},{menuId:"966a7ec0-5ef4-4514-bd10-0043fbca982c",menuItemId:"c042f13b-b49f-4164-8817-c6a9623c7c40",quantity:6},{menuId:"966a7ec0-5ef4-4514-bd10-0043fbca982c",menuItemId:"1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",quantity:2},{menuId:"966a7ec0-5ef4-4514-bd10-0043fbca982c",menuItemId:"a6697045-5c3d-4473-a434-c0674b8f4af2",quantity:1}],menus:[{menuId:"de6368d5-a076-4058-8f93-a0bac39bb451",name:"Canap\xe9 Two",category:"FOOD",menuSections:[{name:"Package ",menuSectionItems:[{itemId:"945dafd8-bf01-4a51-b6c8-a4c863db5d1f",name:"Canap\xe9 Two"}]}]},{menuId:"130c4d6a-ba3c-43fc-917c-17090b26a36e",name:"Canap\xe9 One ",category:"FOOD",menuSections:[{name:"Package ",menuSectionItems:[{itemId:"422ec16c-c9c0-4c3d-a974-021dab39e563",name:"Canap\xe9 One "}]}]},{menuId:"966a7ec0-5ef4-4514-bd10-0043fbca982c",name:"Package Two ",category:"DRINK",menuSections:[{name:"Packages ",menuSectionItems:[{itemId:"c042f13b-b49f-4164-8817-c6a9623c7c40",name:"Package Two - 2 Hours "},{itemId:"1f2b92b6-8a4d-403f-bbf8-92ef2bc0b34b",name:"Package Two - 3 Hours "},{itemId:"a6697045-5c3d-4473-a434-c0674b8f4af2",name:"Package Two - 4 Hours "}]}]}]}}}};

var menus = input.data.event.eventOrder.menus
var menuItemIds = input.data.event.eventOrder.menuItemIds
var obj = menus.reduce(function(agg, menu) {
  menu.menuSections.forEach(function(menu_section) {
    agg[menu_section.name] ??=  {}
    agg[menu_section.name][menu.name] ??= {}
    menu_section.menuSectionItems.forEach(function(section_item) {
    
      var find = menuItemIds.find(item => item.menuItemId === section_item.itemId)
      agg[menu_section.name][menu.name][section_item.name] ??= {}
      agg[menu_section.name][menu.name][section_item.name].QTY = find.quantity
      // same idea for sub items i guess
    })
  })
  return agg;
}, {})


function treeView(tree) {
  var markup = '';

  Object.keys(tree).forEach(function(key) {
    var value = tree[key];
    markup  = '<li>'   (typeof (value)==='object' ? key   treeView(value) : value)   '</li>';
    
  })

  return "<ul>"   markup   "</ul>";
}
// console.log(obj)
document.querySelector("#output").innerHTML = treeView(obj)
.as-console-wrapper {
  max-height: 100% !important
}
<div id="output"></div>

  • Related