Explain Codes LogoExplain Codes Logo

Convert JS Object to form data

javascript
form-data
recursion
file-upload
Alex KataevbyAlex Kataev·Feb 3, 2025
TLDR

Here's a quick conversion of a JavaScript object to FormData, looping through its properties:

const obj = { key1: 'value1', key2: 'value2' }; const formData = new FormData(); Object.entries(obj).forEach(([key, value]) => { formData.append(key, value); // Voilà, an item is packed. });

This walks through the object and adds each property value to the FormData instance, just like packing for a trip.

Handling different data types

Converting nested objects and arrays

In the wild world of internet, your JavaScript object may contain nested objects or arrays. In that case, it's time to flex your recursion skills:

function serialize(data, parentKey, formData = new FormData()) { Object.entries(data).forEach(([key, value]) => { if (value instanceof File) { formData.append(parentKey ? `${parentKey}[${key}]` : key, value); // special pass for File VIPs } else if (typeof value === 'object' && !(value instanceof Date)) { serialize(value, parentKey ? `${parentKey}[${key}]` : key, formData); // Oh look, another level, here we go again! } else { formData.append(parentKey ? `${parentKey}[${key}]` : key, value); // normal objects, nothing fancy. } }); return formData; } const obj = { user: { name: 'Alice', avatar: FileObject } }; const formData = serialize(obj); // Don't worry `serialize()`, we're not judging you... much.

Ignoring the unworthy

Every king has his favorites and so can your FormData. If any object property should not join the FormData party, use an ignore list:

const ignoreList = ['secret', 'deprecated']; Object.entries(obj).forEach(([key, value]) => { if (!ignoreList.includes(key)) { formData.append(key, value); // Welcome to the exclusive club! } });

VIP treatment for files

Beware when your object plays hosts to File instances! Bestow them directly to your FormData, showing the respect they deserve:

if (value instanceof File) { formData.append(key, value, value.name); // Rolling out the red carpet for File data }

Advanced tactics

Harness the power of ES6

Unleash your inner Jedi by leveraging ES6 for a cleaner conversion:

const obj = { key1: 'value1', key2: 'value2' }; const formData = Object.keys(obj).reduce((fd, key) => (fd.append(key, obj[key]), fd), new FormData());

Diving deep with recursive conversion

If your JavaScript object is as nested as a set of Russian dolls, use a recursive function for deep conversion:

const convertToFormData = (obj, fd = new FormData(), prevKey = null) => { Object.entries(obj).forEach(([key, value]) => { const fieldName = prevKey ? `${prevKey}[${key}]` : key; if (value instanceof Object && !(value instanceof File || value instanceof Date)) { return convertToFormData(value, fd, fieldName); // Let's dive deeper... } fd.append(fieldName, value); // The end is near...whoops, not that morbid. }); return fd; };

While submitting data through jQuery's $.ajax(), set processData and contentType to false:

$.ajax({ url: '/target-url', type: 'POST', data: formData, processData: false, // jQuery, stop meddling with our data! contentType: false, // jQuery, do you even MIME? success: function(data) { console.log('Upload successful!'); } });

Error handling and server response

Validation on the server-side

In the realm of security, never trust the client. Always validate FormData on the server-side:

if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) { // All smooth sailing for file upload } else { // Time to manage those pesky file upload errors }

Handling client-side responses

Bask in the sun of jQuery's .done(), absorbing server responses and fending off any errors:

$.ajax(/*...*/).done(function(data) { console.log('Response received:', data); }).fail(function(jqXHR, textStatus) { console.error('Request failed:', textStatus); // Error: the winters of discontent });

Ensuring wide compatibility

Create harmony across IE11 and other modern browsers through vigorous testing.