Generate JSON from form inputs

#es6 #howto #javascript

September 10, 2018
by Matteo Bertozzo

Find more about
[development]

While there are tons of libraries to manage forms and to handle input values, here’s a vanilla Javascript implementation of a function to create a JSON object mapping a form structure.

The interesting thing about this implementation is that it can be applied to any form without any change and doesn’t require any additional markup: all you’ll have to do is to name wisely your input fields.

Keep on reading to find how to get the following final JSON object out of a form!

{
  "title": "",
  "text": {
    "headline": "",
    "text": ""
  }
  "media": {
    "url": "",
    "caption": ""
  }
}

Let’s get started

First of all, we have to build the form: I’m going to recreate the same structure defined in the snippet above.

<form id="json">
  <input type="text" name="title" />
  <input type="text" name="text.headline" />
  <input type="text" name="text.text" />
  <input type="text" name="media.caption" />
  <input type="text" name="media.credit" />
  <input type="text" name="media.url" />
</form>

<button id="getDataBtn">Get JSON Data</button>

As you can see, I’ve used specific values for the input names, using something that resembles the dot notation when we want nested JSON objects.

Now we have to write a function that will read the name and value for each of the input fields and will build the proper object, nesting when necessary (thanks to Sean Yang for the tip!).

const generateObj = (obj, arr, val) => {
  if (arr.length === 1) {
    obj[arr[0]] = val;
    return;
  }

  if (!obj[arr[0]]) {
    obj[arr[0]] = {};
  }

  const restArr = arr.splice(1);
  generateObj(obj[arr[0]], restArr, val);
}

Basically, this is a recursive function that accepts three arguments: obj is the initial object that will be updated with the processed data, arr is the array resulting from splitting the input name by the dots, val is the input value. The inner working may be clearer once we invoke generateObj with the actual data.

So, let’s proceed defining the following function that triggers the form elaboration:

const getData = (id) => {
  const form = document.getElementById(id);
  const inputCollection = form.getElementsByTagName('input');
  const inputArray = [...inputCollection];
  const data = {};

  inputArray.map(input => {
    const { name, value } = input;
    const splitName = name.split('.');
    generateObj(data, splitName, value);
  })

  return data;
}

Please note we used ES6 spread operator to convert the HTML Collection holding the references to each form input to an array we can loop through.

At this point we just have to fire the getData(id) function with the appropriate argument when the submit button is clicked:

const getDataBtn = document.getElementById('getDataBtn');

getDataBtn.addEventListener('click', () => {
  const data = getData('json');
  console.log(JSON.stringify(data));
})

That’s it!
When submitting the form we’ll get the generated JSON printed to the console. You can now perform any kind of actions with the data by just adding your logic instead of the console.log() instruction.