Flatten JavaScript Object for use with FormData

This is something I thought that no one would ever need but looking at this gist. The stars, forks and comments proved me wrong.

I needed to flatten an object as well as wanted to send over some data from a VueJS frontend as multipart/form-data and on the backend it was PHP so I needed the field names to be like

"name" : "value", 
"nested[0][name]": "value",
"nested[0][age]": "value"

The comments in the gist had the following function which I modified a bit to be like:

/**
 * Flatten object to be of form key[subkey] for sending in multipart/form-data
 * Use for simple data types, with multi level nesting
 * @param {*} object
 */
flatten(object) {
  return Object.assign({}, ...function _flatten(objectBit, path = '', left =
    "[", right = "]") {
    return [].concat(
      ...Object.keys(objectBit).map(
        key => typeof objectBit[key] === 'object' ?
        _flatten(objectBit[key], `${path}${left}${key}${right}`) :
        ({
          [`${path}${left}${key}${right}`]: objectBit[key]
        }) //append object with it’s path as key
      )
    )
  }(object, '', '', ''));
}

I added the left, right variables. As I didn’t need the brackets for the very first level, I put left and right as ” for the very first call to _flatten. The variables give more flexibility as I can change them later to get output likenested.0.name or /nested/0/name by playing around with them.

This function allows me to call it like:

flatten({
  "id": 3,
  "name": "Montserrat",
  "signatures": [
    {
      "name": "Susanna Towne",
      "image_url": "https://lorempixel.com/50/50/?90502"
    },
    {
      "name": "Tremaine Durgan",
      "image_url": "https://lorempixel.com/50/50/?79275"
    },
    {
      "name": "Dr. Julia Block",
      "image_url": "blob:http://localhost:8000/def8a73e-c437-4d5c-bef8-3e7b44605928"
    },
    {
      "name": "Victoria Keebler",
      "image_url": "https://lorempixel.com/50/50/?83540"
    },
    {
      "name": {
        "abc": "xyz"
      },
      "image_url": "blob:http://localhost:8000/6caf4ce1-8084-409b-82c1-7ede1e72f3c9"
    }
  ]
});

and get output as:

{
  "id": 3,
  "name": "Montserrat",
  "signatures[0][name]": "Susanna Towne",
  "signatures[0][image_url]": "https://lorempixel.com/50/50/?90502",
  "signatures[1][name]": "Tremaine Durgan",
  "signatures[1][image_url]": "https://lorempixel.com/50/50/?79275",
  "signatures[2][name]": "Dr. Julia Block",
  "signatures[2][image_url]": "blob:http://localhost:8000/def8a73e-c437-4d5c-bef8-3e7b44605928",
  "signatures[3][name]": "Victoria Keebler",
  "signatures[3][image_url]": "https://lorempixel.com/50/50/?83540",
  "signatures[4][name][abc]": "xyz",
  "signatures[4][image_url]": "blob:http://localhost:8000/6caf4ce1-8084-409b-82c1-7ede1e72f3c9"
}

Check how it even goes below level 1 of nesting and the output is exactly what I wanted.

Leave a Reply

Your email address will not be published. Required fields are marked *