Serialize form data

Turn a form’s fields into an object; repeated names become arrays.

JavaScriptBrowser · DOM Version 1.0.0 · MIT · .md

serialize-form-data.js
function serialize(form) {
  const groups = new Map();
  for (const [key, value] of new FormData(form)) groups.set(key, [...(groups.get(key) ?? []), value]);
  return Object.fromEntries([...groups].map(([key, values]) => [key, values.length > 1 ? values : values[0]]));
}

Usage

Markup

fixture.html
<form id="signup">
  <input name="email" value="[email protected]">
  <input name="alias" value=""><input name="alias" value="ana.s">
  <input type="checkbox" name="topic" value="product" checked>
  <input type="checkbox" name="topic" value="security" checked>
  <input type="checkbox" name="topic" value="events">
</form>

Script

usage.js
serialize(document.querySelector('#signup')); // → { email: '[email protected]', alias: ['', 'ana.s'], topic: ['product', 'security'] }

Lines marked → were executed in headless Chromium against the markup above, and each result was compared with the value shown. Lines marked e.g. are illustrative.

Know the limits

  • The original tested the first value for truthiness, so an empty first value was dropped: alias would have been "ana.s".
  • Unchecked checkboxes and disabled fields are not submitted, so they are absent, like the events topic. File inputs produce File objects, which JSON cannot carry; send the FormData itself for uploads.
  • Object.fromEntries keeps a field named __proto__ as ordinary data.

The function above is the code the usage lines run. It does not validate its arguments; add checks where it receives untrusted input.

Source & maintenance

Based on Serialize form data from the original 1loc collection by Nguyen Huu Phuoc. Copyright (c) 2020 phuoc-ng. MIT licensed.

Keeps empty first values and __proto__ field names; the original dropped an empty first value. Executed in Chromium. Original MDX retained as inert source evidence.

Maintained by Oveyon. Source commit: 14b481cf60df. Read the license.

Usage lines executed in headless Chromium against the fixture markup; no external services · reviewed October 28, 2026.

Keep exploring

Type two or more characters. Try “duplicate”, “webhook” or “retry”.