Michal Kubiak
Michal Kubiak

Reputation: 57

JSON nested object reduce or flatten

I need to flatten this JSON to have no nests just shellfish and then the name of it etc. Thanks in advance! I tried a few things so maybe reduce or map but I don't know enough about those to attack the problem, any online resources specific to problems like this you guys can share? I work with these a lot would be very handy to master!

"data": [
        {
            "name": "Batch1",
            "description": "seed",
            "age": 2,
            "quantity": 1000,
            "source": "Hatchery",
            "hatchery": "robs hatchery",
            "location": "dingle",
            "shellfish": {
                "name": "oyster"
            },
            "grade_list": {
                "name": "Grade0"
            },
            "stock_type": {
                "name": "seeds"
            }
        },
        {
            "name": "Batch2",
            "description": "Batch2",
            "age": 20,
            "quantity": 15700,
            "source": "aka",
            "hatchery": "aka",
            "location": "dingle",
            "shellfish": {
                "name": "oyster"
            },
            "grade_list": {
                "name": "Grade1"
            },
            "stock_type": {
                "name": "mature"
            }
        },
        {
            "name": "5555",
            "description": "45",
            "age": 1,
            "quantity": 134,
            "source": "fhh",
            "hatchery": "hfhj",
            "location": "garden",
            "shellfish": {
                "name": "oyster"
            },
            "grade_list": {
                "name": "Grade0"
            },
            "stock_type": {
                "name": "seeds"
            }
        }
    ]

Edit: I need this to have no nests and look like this:

"data": [
        {
            "name": "Batch1",
            "description": "seed",
            "age": 2,
            "quantity": 1000,
            "source": "Hatchery",
            "hatchery": "robs hatchery",
            "location": "dingle",
            "shellfish": {
                "name": "oyster"
            },
            "grade_list": {
                "name": "Grade0"
            },
            "stock_type": {
                "name": "seeds"
            }
        },
        {
            "name": "Batch2",
            "description": "Batch2",
            "age": 20,
            "quantity": 15700,
            "source": "aka",
            "hatchery": "aka",
            "location": "dingle",
            "shellfish": {
                "name": "oyster"
            },
            "grade_list": {
                "name": "Grade1"
            },
            "stock_type": {
                "name": "mature"
            }
        },
        {
            "name": "5555",
            "description": "45",
            "age": 1,
            "quantity": 134,
            "source": "fhh",
            "hatchery": "hfhj",
            "location": "garden",
            "shellfish": "oyster",
            "grade_list": "Grade0",
            "stock_type": "seeds"
        }
    ]

Upvotes: 0

Views: 564

Answers (2)

Daniel Beck
Daniel Beck

Reputation: 21485

This will flatten any sub-object into a single key-value pair; it will only work if the sub-object has the single key "name" containing the intended value. Comments in the code explain how it works:

const data = {
  "data": [{
      "name": "Batch1",
      "description": "seed",
      "age": 2,
      "quantity": 1000,
      "source": "Hatchery",
      "hatchery": "robs hatchery",
      "location": "dingle",
      "shellfish": {
        "name": "oyster"
      },
      "grade_list": {
        "name": "Grade0"
      },
      "stock_type": {
        "name": "seeds"
      }
    },
    {
      "name": "Batch2",
      "description": "Batch2",
      "age": 20,
      "quantity": 15700,
      "source": "aka",
      "hatchery": "aka",
      "location": "dingle",
      "shellfish": {
        "name": "oyster"
      },
      "grade_list": {
        "name": "Grade1"
      },
      "stock_type": {
        "name": "mature"
      }
    },
    {
      "name": "5555",
      "description": "45",
      "age": 1,
      "quantity": 134,
      "source": "fhh",
      "hatchery": "hfhj",
      "location": "garden",
      "shellfish": "oyster",
      "grade_list": "Grade0",
      "stock_type": "seeds"
    }
  ]
}

const transform = (input) => {
  // step through each object in the array
  for (obj of input.data) {
    // step through each key in the object
    for (k of Object.keys(obj)) {
      // if that key contains an object:
      if (typeof(obj[k])==='object') {
        // replace the object with its own 'name' field
        obj[k] = obj[k].name
      }
    }
  }
  return input
}

console.log(transform(data))

Upvotes: 1

Mathias Gheno
Mathias Gheno

Reputation: 787

If you want to make this process more automated for all the elements of your array you can use the map to change all the elements that have the prop name.

const response = {
  "data": [
    {
      "name": "Batch1",
      "description": "seed",
      "age": 2,
      "quantity": 1000,
      "source": "Hatchery",
      "hatchery": "robs hatchery",
      "location": "dingle",
      "shellfish": {
        "name": "oyster"
      },
      "grade_list": {
        "name": "Grade0"
      },
      "stock_type": {
        "name": "seeds"
      }
    },
    {
      "name": "Batch2",
      "description": "Batch2",
      "age": 20,
      "quantity": 15700,
      "source": "aka",
      "hatchery": "aka",
      "location": "dingle",
      "shellfish": {
        "name": "oyster"
      },
      "grade_list": {
        "name": "Grade1"
      },
      "stock_type": {
        "name": "mature"
      }
    },
    {
      "name": "5555",
      "description": "45",
      "age": 1,
      "quantity": 134,
      "source": "fhh",
      "hatchery": "hfhj",
      "location": "garden",
      "shellfish": {
        "name": "oyster"
      },
      "grade_list": {
        "name": "Grade0"
      },
      "stock_type": {
        "name": "seeds"
      }
    }
  ]
}

const result = response.data.map((element) => {
  const keysWithNameProp = Object.keys(element).filter(key => element[key].name !== undefined);
  const copyOfElement = {...element};
  keysWithNameProp.forEach(prop => {
    copyOfElement[prop] = element[prop].name;
  })
  return copyOfElement;
});

console.log(result);

Is this code the first thing is done is to have the list of all the keys that have the name prop. With that list now I can iterate over it and change the object prop to use just the value of the name.

Upvotes: 1

Related Questions