😳

Flattening nested objects

Problem

You have an object with a load of deeply nested child objects within it

Answer

Everyone’s favourite Array.reduce to the rescue

Breakdown

So we need a way of iterating over all of the fields inside the object. This can be done very simply with the Object.keys function. This little beauty passes you back an Array of each key which exists in your object. This will allow us to iterate over each field. Check.

Overall we need to turn this array into a new flattened object. Many items into one item. That sounds like a reduction, so lets use reduce

Reduce accepts a function. This function takes as its arguments (accumulator, item, index)

So reduce is going to work basically like Array.map its going to iterate over each item in the array it is called on, and call your function using that item. Except, with this function instead you have reference to the previously returned value. The acculumated value.

With our array of keys of the object we can then run reduce over it, so that it calls our function for each key. This will then allow us to check if the value at that key is an object or just a regular value. If it is an object then we get grab all of its properties and spread them out into the new object we want to return.

Object.keys(obj).reduce((acc, key) => {
  const value = obj[key];
  return typeof value === "object"
    ? { ...acc, ...value }
    : { ...acc, key: value };
});

One other thing to note is that we want to return a new object, so it makes sense to start with an empty object, which we will then fill up with key, value pairs. Reduce takes a second argument which is the initial value of the accumulator so in our case it will be {}

The Final Product

const flatten = (obj) =>
  Object.keys(obj).reduce((acc, key) => {
    const value = obj[key];
    return typeof value === "object"
      ? { ...acc, ...flatten(value) }
      : { ...acc, key: value };
  }, {});

Beware

There is one big problem with this implementation. If the names of 2 keys are the same, the second will overwrite the first! A bonus for YOU the reader will be to adapt this cheeky flatten function to allow it to accept conflicting names. Accept the challenge at your own peril!