Skip to main content Accessibility Feedback

How to serialize form data with vanilla JS

UPDATE: This article was updated to account for forms with multiple fields that have the same name.

Historically, getting data from a form into a format you could send to an API was a bit difficult, but modern techniques make it a lot easier.

The FormData object

The FormData object provides an easy way to serialize form fields into key/value pairs.

You can use the new FormData() constructor to create a new FormData object, passing in the form to serialize as an argument. Form fields must have a name attribute to be included object. Otherwise, they’re skipped. The id property doesn’t count.

For example, if you have a form that looked like this…

<form id="post">

	<label for="title">Title</label>
	<input type="text" name="title" id="title" value="Go to the beach">

	<label for="body">Body</label>
	<textarea id="body" name="body">Soak up the sun and swim in the ocean.</textarea>

	<input type="hidden" name="userId" value="1">

	<button>Submit</button>

</form>

You would serialize it like this…

// Get the form
let form = document.querySelector('#post');

// Get all field data from the form
// returns a FormData object
let data = new FormData(form);

Looping through FormData

The FormData object is an iterable, which means you can loop through it using a for...of loop (you’ll notice that a trend with many of the newer JS methods).

Each entry in the loop is an array of key/value pairs.

// logs...
// ["title", "Go to the beach"]
// ["body", "Soak up the sun and swim in the ocean."]
// ["userId", "1"]
for (let entry of data) {
	console.log(entry);
}

Because the entry values are arrays, you can also use array destructuring to assign the key and value to their own variables within the for...of loop.

// logs "title", "Go to the beach", etc.
for (let [key, value] of data) {
	console.log(key);
	console.log(value);
}

Adding, updating, and removing items from a FormData object

The FormData object has several methods that you can use to add, remove, and update items.

Use the FormData.set() method to replace an existing entry, or add a new one if an entry with that key doesn’t exist. Pass in the key and value as arguments.

// Updates the userId field with a new value
data.set('userId', '3');

// Creates a new key, "date", with a value of "4"
data.set('date', 'July 4');

Use the FormData.append() method to add a new entry, passing in the key and value as arguments. If an item with that key already exists, another one is added and the existing one is unaffected.

// Add a second "body" key to the data FormData object
data.append('body', 'Eat ice cream');

Use the FormData.delete() method to delete an entry, passing in the key as an argument. If more than one item with that key exist, all of them are deleted.

// Delete items with the "body" key
data.delete('body');

How to convert a FormData object into an object or query string

The FormData object can be submitted as-is to some endpoints with a content-type header of multipart/form-data, not not all APIs support that.

To serialize a FormData object into a query string, pass it into the new URLSearchParams() constructor. This will create a URLSearchParams object of encoded query string values.

Then, call the URLSearchParams.toString() method on it to convert it into a query string.

// Get the form
let form = document.querySelector('#post');

// Get all field data from the form
let data = new FormData(form);

// Convert to a query string
let queryString = new URLSearchParams(data).toString();

To serialize a FormData object into a plain object, we need to loop through each entry with a for...of loop and add it to an object.

let obj = {};
for (let [key, value] of data) {
	obj[key] = value;
}

But, if there’s more one form field with the same name, the original value will get overwritten. To account for this, we need to check if the key already exists in the obj. If it does, we want to convert it to an array and Array.push() the new value into it.

let obj = {};
for (let [key, value] of data) {
	if (obj[key] !== undefined) {
		if (!Array.isArray(obj[key])) {
			obj[key] = [obj[key]];
		}
		obj[key].push(value);
	} else {
		obj[key] = value;
	}
}

Here’s a helper function you can use to convert a FormData object into a plain object. Pass in the FormData object as an argument.

function serialize (data) {
	let obj = {};
	for (let [key, value] of data) {
		if (obj[key] !== undefined) {
			if (!Array.isArray(obj[key])) {
				obj[key] = [obj[key]];
			}
			obj[key].push(value);
		} else {
			obj[key] = value;
		}
	}
	return obj;
}

And here’s how you would use it.

// Get the form
let form = document.querySelector('#post');

// Get all field data from the form
let data = new FormData(form);

// Convert to an object
let formObj = serialize(data);