FormData append nested object


Is it possible to append nested object to FormData?

let formData = new FormData();
let data = {
    title: 'title',
    text: 'text',
    preview: {p_title:'p title', p_text: 'p text'}
};

$.each(data, function(key, value) {
    formData.append(key, value);
});

Server console - console.log(req.body)

{
    title: 'title',
    text: 'text',
    preview: '[object Object]'
}

How can I get the exact value of preview: {p_title:'p title', p_text: 'p text'}?

FormData values are automatically converted to string. You can try to do it using Blob.

Or just put it as string using JSON.stringify(obj).

$.each(data, function(key, value){
    if (typeof(value) === 'object') {
        value = new Blob([JSON.stringify(value)], {type : 'application/json'});// or just JSON.stringify(value)
    }
    formData.append(key, value);
});

Here is a "A convenient JavaScript function that converts an object to a FormData instance" github, also available as a npm package, very simple to use

let data = {
    title: 'title',
    text: 'text',
    preview: {p_title:'p title', p_text: 'p text'}
};

var formData = objectToFormData(data);

To append an object to formData, you need to stringify it first, like this:

let objToAppend= {
  key1: value1,
  key2: value2,
}
let formData = new FormDate();
formData.append('obj', JSON.stringify(objToAppend));

Then on the server side to access it you need to parse it first using JSON.parse(). Hope it helps!


let formData = new FormData();
let data = {
  title: 'title',
  text: 'text',
  preview: {p_title:'p title', p_text: 'p text'}
};

for(let dataKey in data) {
  if(dataKey === 'preview') {
    // append nested object
    for (let previewKey in data[dataKey]) {
      formData.append(`preview[${previewKey}]`, data[dataKey][previewKey]);
    }
  }
  else {
    formData.append(dataKey, data[dataKey]);
  }
}

Console formData

for (let val of formData.entries()) {
  console.log(val[0]+ ', ' + val[1]); 
}

Try out object-to-formdata. It's a convenient JavaScript function that converts Objects to FormData instances.

import { objectToFormData } from 'object-to-formdata';

const object = {
  /**
   * key-value mapping
   * values can be primitives or objects
   */
};

const options = {
  /**
   * include array indices in FormData keys
   * defaults to false
   */
  indices: false,

  /**
   * treat null values like undefined values and ignore them
   * defaults to false
   */
  nullsAsUndefineds: false,

  /**
   * convert true or false to 1 or 0 respectively
   * defaults to false
   */
  booleansAsIntegers: false,
};

const formData = objectToFormData(
  object,
  options, // optional
  existingFormData, // optional
  keyPrefix, // optional
);

console.log(formData);


This for me do the work:

use . to separate key and subKey

let formData = new FormData();
let data = {
  title: 'title',
  text: 'text',
  preview: {p_title:'p title', p_text: 'p text'}
};

for(let key in data) {
  if(typeof(data[key]) === 'object') {
    for (let subKey in data[key]) {
      formData.append(`${key}.${subKey}`, data[key][subKey]);
    }
  }
  else {
    formData.append(key, data[key]);
  }
}

You don't need to use any third party modules and JSON.stringify() isn't ideal if you have nested objects. Instead you can use Object.entries().

// If this is the object you want to convert to FormData...
const item = {
    description: 'First item',
    price: 13,
    photo: File
};

const formData = new FormData();

Object.entries(item).forEach(([key, value]) => {
    formData.append(key, value);
});

// At this point, you can then pass formData to your handler method

Read more about Object.entries() over here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries