skip to Main Content

I am using a library that returns a filtered version of results. The problem is that the results add an additional "item" layer for each object that is in an array which is not the format I need. Note below how both units and depts are wrapped in the "ITEM":{} object. I want to remove that item layer using just vanilla javascript.

{
  "units": [
    {
      "ITEM": {
        "UnitName": "Unit1",
        "UnitID": 1,
        "depts": [
          {"ITEM": {"DeptName": "Dept1-1"}}
        ]
      }
    },
    {
      "ITEM": {
        "UnitName": "Unit2",
        "UnitID": 2,
        "depts": [
          {"ITEM": {"DeptName": "Dept2-1"}},
          {"ITEM": { "DeptName": "Dept2-2"}}
        ]
      }
    }
  ]
}

I would like to partially flatten this so it looks like the following.

{
  "units": [
    {
        "UnitName": "Unit1",
        "UnitID": 1,
        "depts": [
          {"DeptName": "Dept1-1"}
        ]
    },
    {
        "UnitName": "Unit2",
        "UnitID": 2,
        "depts": [
          {"DeptName": "Dept2-1"},
          { "DeptName": "Dept2-2"}
        ]
    }
  ]
}

Because I will be repeating this for other data, I’m trying to figure out a generic function to remove this extra layer whenever there is an "item" object wrapped around every returned object in an array.
However, every example I can find to flatten a javascript object assumes I want the entire thing flattened. Example 1, Example 2

I’m sure there has got to be an existing solution already, but I probably need to use another word other than flattening to find the right results. Help would be greatly appreciated!

2

Answers


  1. You can use Object.assign and map on array to achieve that:

    data = Object.assign(data, {
      "units": data.units
        .map((u) => Object.assign(u.ITEM, {
           "depts": u.ITEM.depts
             .map((d) => d.ITEM) 
        }))
    });
    
    Login or Signup to reply.
  2. you can recursively traverse the object tree and clean up:

    // traverses the object tree and replaces `{ ITEM: ??? }` with the `???`
    function removeITEM(item) {
      if (typeof item !== "object" || item === null) return item;
    
      if (Array.isArray(item)) return item.map(removeITEM);
    
      // that's where the cleanup happens
      if (item.ITEM) return removeITEM(item.ITEM);
    
      let copy = {};
      for (let key in item) {
        copy[key] = removeITEM(item[key]);
      }
      return copy;
    }
    
    console.log(removeITEM({
      "units": [
        {
          "ITEM": {
            "UnitName": "Unit1",
            "UnitID": 1,
            "depts": [
              { "ITEM": { "DeptName": "Dept1-1" } }
            ]
          }
        },
        {
          "ITEM": {
            "UnitName": "Unit2",
            "UnitID": 2,
            "depts": [
              { "ITEM": { "DeptName": "Dept2-1" } },
              { "ITEM": { "DeptName": "Dept2-2" } }
            ]
          }
        }
      ]
    }));
    .as-console-wrapper{top:0;max-height:100%!important}

    Or maybe an alternative: If you have access to the JSON string (like from a ajax request) it may be an option to clean the data structure up on JSON.parse():

    const json = '{"units":[{"ITEM":{"UnitName":"Unit1","UnitID":1,"depts":[{"ITEM":{"DeptName":"Dept1-1"}}]}},{"ITEM":{"UnitName":"Unit2","UnitID":2,"depts":[{"ITEM":{"DeptName":"Dept2-1"}},{"ITEM":{"DeptName":"Dept2-2"}}]}}]}';
    
    console.log(JSON.parse(json, (key, value) => (value && value.ITEM) ?? value));
    .as-console-wrapper{top:0;max-height:100%!important}
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search