Decode FormData to JavaScript Object

0.9.0 · active · verified Sun Apr 19

`decode-formdata` is a JavaScript and TypeScript library designed to convert a flat `FormData` object back into a complex, nested JavaScript object. This process addresses the inherent data loss when `FormData` serializes all values to strings or `File` objects, and flattens nested structures. The library, currently at version 0.9.0, is actively maintained with recent updates focusing on bug fixes, security enhancements, and improved parsing capabilities like array bracket notation. It does not follow a strict release cadence but receives updates as needed. Its primary utility lies in reconstructing type information (booleans, numbers, dates) and object/array hierarchies from form field names using dot and bracket notation. This makes it particularly valuable for server-side processing in full-stack frameworks (e.g., Next.js, Remix, SvelteKit) where `FormData` is common for progressively enhanced forms, allowing developers to easily validate and type the re-hydrated data with schema libraries like Zod or Valibot.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to use `decode` to transform a `FormData` object, populated with various data types and nested structures, back into a complex JavaScript object. It highlights specifying array paths, and type conversions for booleans, dates, files, and numbers, mimicking a common server-side form handling scenario.

import { decode } from 'decode-formdata';

// In a Node.js environment, you might need to polyfill FormData
// or use a library like 'form-data-polyfill' if not using Node 16+ which has it globally.
// For browser or modern environments (like Cloudflare Workers, Deno, Bun), FormData is globally available.

async function handleFormSubmission() {
  // Simulate receiving FormData from an HTTP request (e.g., request.formData() in a web framework)
  const formData = new FormData();

  // Populate the FormData object with various types of data and nesting
  formData.append('title', 'Red apple');
  formData.append('price', '0.89');
  formData.append('created', '2023-10-09');
  formData.append('active', 'on'); // 'on' is a common representation for true from checkboxes
  formData.append('tags.0', 'fruit');
  formData.append('tags.1', 'healthy');
  formData.append('tags.2', 'sweet');
  formData.append('images.0.title', 'Close up of an apple');
  formData.append('images.0.created', '2023-08-24');
  formData.append('images.0.file', new Blob(['image-data-1'], { type: 'image/png' }), 'apple.png');
  formData.append('images.1.title', 'Our fruit fields at Lake Constance');
  formData.append('images.1.created', '2023-08-12');
  formData.append('images.1.file', new Blob(['image-data-2'], { type: 'image/jpeg' }), 'fields.jpg');

  // Decode the FormData into a JavaScript object, specifying expected types and array paths
  const formValues = decode(formData, {
    arrays: ['tags', 'images'], // 'tags' is a simple array, 'images' is an array of objects
    booleans: ['active'],       // 'active' field should be parsed as a boolean
    dates: ['created', 'images.$.created'], // 'created' and 'images[i].created' fields as Date objects
    files: ['images.$.file'],   // 'images[i].file' fields as File/Blob objects
    numbers: ['price'],         // 'price' field as a number
  });

  console.log('Decoded Form Values:', formValues);

  // Expected output structure:
  // {
  //   title: 'Red apple',
  //   price: 0.89,
  //   created: <Date object for 2023-10-09>,
  //   active: true,
  //   tags: ['fruit', 'healthy', 'sweet'],
  //   images: [
  //     {
  //       title: 'Close up of an apple',
  //       created: <Date object for 2023-08-24>,
  //       file: <Blob object for apple.png>
  //     },
  //     {
  //       title: 'Our fruit fields at Lake Constance',
  //       created: <Date object for 2023-08-12>,
  //       file: <Blob object for fields.jpg>
  //     }
  //   ]
  // }
}

handleFormSubmission();

view raw JSON →