Home
Home
All Posts

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:

Want to receive approximately one email every month with new articles, tools, and references I've discovered? Sign up below.

Read past issues.

Home
Social Links
Site References