Home

Converting FormData to JSON in JavaScript

FormData is a useful interface for collecting data from a form. But it can be tricky to convert to JSON.

The FormData interface is a super convenient way to collect data from a <form> element. This makes the process of submitting form requests asynchronously a total walk in the park.

Most of the time.

It works really great out of the box if you're able to send your request using the multipart/form-data encoding type. But what often happens is the service that is receiving that data isn't setup to work with that encoding. That's because it's not as easy to work with. It's often a cleaner approach to be able to accept JSON on the server side and use that to (do whatever) with the form data.

Sending FormData Directly

Let's say we have a super simple form, with one field to collect a name:

<form onsubmit="submitForm(event)">
<label>Name</label>
<br />
<input type="text" name="name" required />
<br /><br />
<input type="submit" value="Submit" />
</form>
note

Don't actually use onsubmit to call a global function in production. Here are a couple alternate patterns worth considering.

We could then submit the data through some JavaScript function:

function submitForm(event) {
// Prevent the form from submitting.
event.preventDefault();
// Set url for submission and collect data.
const url = "https://example.com/...";
const formData = new FormData(event.target);
// Submit the data.
const request = new XMLHttpRequest();
request.open("POST", url);
request.send(formData);
}

That works great if your server (or serverless function) can process the data directly.

Converting FormData to JSON

Now here's the weird thing. If you inspect formData from the function above, it looks like there's nothing there.

Let's adjust our function:

function submitForm(event) {
// Prevent the form from submitting.
event.preventDefault();
// Set url for submission and collect data.
const url = "https://example.com/...";
const formData = new FormData(event.target);
// Log the data.
console.log(formData);
}

This will result in a log to the console like this:

FormData {}

Coooool. That's not helpful.

Instead, we actually have to iterate over the field individually and build an object manually.

function submitForm(event) {
// Prevent the form from submitting.
event.preventDefault();
// Set url for submission and collect data.
const url = "https://example.com/...";
const formData = new FormData(event.target);
// Build the data object.
const data = {};
formData.forEach((value, key) => (data[key] = value));
// Log the data.
console.log(data);
}

Now fill in the field with something like "My Name" and submit the form. You'll see the object logged to the console:

{
name: "My Name";
}

Handling All Cases

That will solve for many cases, but not all. This StackOverflow answer offers a solution for handling multi-select lists. Check out the demo.


References:

Let's Connect

Keep Reading

2 Ways to Keep JavaScript Local

It's far too easy to let your JS code pollute the global namespace. Here are two methods for keeping your code local.

May 21, 2018

Convert Markdown Image to HTML in VS Code

Make a bulk conversion of markdown images to HTML strings using a regex find and replace with VS Code.

May 03, 2022

Compile ES6 Code with Gulp and Babel, Part 4

In the fourth of five parts on compiling multiple ES6 files into a minified bundle, you will learn how to minify your bundle and automatically clean up temporary build files.

Dec 20, 2018