How to convert FormData (HTML5 object) to JSON

How to convert HTML5 FormData object to JSON? Without jquery and handling nested properties in FormData as an object.

+54
javascript form-data
source share
15 answers

You can also use forEach directly for the FormData object:

 var object = {}; formData.forEach(function(value, key){ object[key] = value; }); var json = JSON.stringify(object); 

UPDATE:

And for those who prefer the same solution with ES6 arrows :

 var object = {}; formData.forEach((value, key) => {object[key] = value}); var json = JSON.stringify(object); 

UPDATE 2:

And for those who need support for multiple choice lists or other form elements with multiple values ​​(since there are so many comments under the answer to this problem, I will add a possible solution):

 var object = {}; formData.forEach((value, key) => { if(!object.hasOwnProperty(key)){ object[key] = value; return; } if(!Array.isArray(object[key])){ object[key] = [object[key]]; } object[key].push(value); }); var json = JSON.stringify(object); 

Here is a fiddle demonstrating the use of this method with a simple multiple-choice list.

UPDATE 3:

As an additional note for those ending here, if the goal of converting the form data to json is to send it via an XML XML request to the server, you can send the FormData object directly without converting it. As simple as this:

 var request = new XMLHttpRequest(); request.open("POST", "http://example.com/submitform.php"); request.send(formData); 

See also also Using FormData objects in MDN for reference :

UPDATE 4:

As mentioned in one of the comments below my answer, the JSON stringify method will not work out of the box for all types of objects. For more information about which types are supported, I would like to refer to the description section in the MDN JSON.stringify .

The description also mentions that:

If the toJSON () method has a value, it determines which data will be serialized.

This means that you can provide your own toJSON serialization toJSON with logic to serialize your custom objects. This way you can quickly and easily create serialization support for more complex object trees.

+85
source share

In 2019, this task became ultralight.

 JSON.stringify(Object.fromEntries(formData)); 

Object.fromEntries : supported on Chrome 73+, Firefox 63+, Safari 12.1

+28
source share

Here's a way to do it in a more functional style, without using a library.

 Array.from(formData.entries()).reduce((memo, pair) => ({ ...memo, [pair[0]]: pair[1], }), {}); 

Example:

 document.getElementById('foobar').addEventListener('submit', (e) => { e.preventDefault(); const formData = new FormData(e.target); const data = Array.from(formData.entries()).reduce((memo, pair) => ({ ...memo, [pair[0]]: pair[1], }), {}); document.getElementById('output').innerHTML = JSON.stringify(data); }); 
 <form id='foobar'> <input name='baz' /> <input type='submit' /> </form> <pre id='output'>Input some value and submit</pre> 
+18
source share

If you have several records with the same name, for example, if you use <SELECT multiple> or have several <INPUT type="checkbox"> with the same name, you need to take care of this and create an array of values. Otherwise, you will only get the last selected value.

Here is a modern ES6 version:

 function formToJSON( elem ) { let output = {}; new FormData( elem ).forEach( ( value, key ) => { // Check if property already exist if ( Object.prototype.hasOwnProperty.call( output, key ) ) { let current = output[ key ]; if ( !Array.isArray( current ) ) { // If it not an array, convert it to an array. current = output[ key ] = [ current ]; } current.push( value ); // Add the new value to the array. } else { output[ key ] = value; } } ); return JSON.stringify( output ); } 

A bit older code (but IE11 is still not supported as it does not support ForEach or entries in FormData )

 function formToJSON( elem ) { var current, entries, item, key, output, value; output = {}; entries = new FormData( elem ).entries(); // Iterate over values, and assign to item. while ( item = entries.next().value ) { // assign to variables to make the code more readable. key = item[0]; value = item[1]; // Check if key already exist if (Object.prototype.hasOwnProperty.call( output, key)) { current = output[ key ]; if ( !Array.isArray( current ) ) { // If it not an array, convert it to an array. current = output[ key ] = [ current ]; } current.push( value ); // Add the new value to the array. } else { output[ key ] = value; } } return JSON.stringify( output ); } 
+7
source share

You can achieve this with a FormData () object. This FormData object will be filled with the current keys / values ​​of the form, using the name property of each element for the keys and their submitted value for the values. It will also encode the contents of the input file.

Example:

 var myForm = document.getElementById('myForm'); myForm.addEventListener('submit', function(event) { event.preventDefault(); var formData = new FormData(myForm), result = {}; for (var entry of formData.entries()) { result[entry[0]] = entry[1]; } result = JSON.stringify(result) console.log(result); }); 
+6
source share

Easy to use function

I created a function for this

 function FormDataToJSON(FormElement){ var formData = new FormData(FormElement); var ConvertedJSON= {}; for (const [key, value] of formData.entries()) { ConvertedJSON[key] = value; } return ConvertedJSON } 

Usage example

 var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');) 

In this code, I created an empty JSON variable using the for loop. I used the key from the formData Object for the JSON Keys in each Itration.

You will find this code in my JS library on GitHub. Suggest me if he needs improvement. I posted the code here https://github.com/alijamal14/Utilities/blob/master/Utilities.js p>

+5
source share

This post is already a year old ... but I really really like ES6 @dzuc's answer. However, it is incomplete because it cannot handle multiple selections or checkboxes. This has already been indicated, and code solutions have been proposed. I find them heavy and not optimized. Therefore, I wrote 2 versions based on @dzuc to handle these cases:

  • For ASP-style forms where the name of several elements can simply be repeated.
 let r=Array.from(fd).reduce( (o , [k,v]) => ( (!o[k]) ? {...o , [k] : v} : {...o , [k] : [...o[k] , v]} ) ,{} ); let obj=JSON.stringify(r); 

Single line version of Hotshot:

 Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{}); 
  • For forms in the style of PHP, where the names of several elements must have the suffix [] .
 let r=Array.from(fd).reduce( (o , [k,v]) => ( (k.split('[').length>1) ? (k=k.split('[')[0] , (!o[k]) ? {...o , [k] : [v]} : {...o , [k] : [...o[k] , v ]} ) : {...o , [k] : v} ) ,{} ); let obj=JSON.stringify(r); 

Single line version of Hotshot:

 Array.from(fd).reduce((o,[k,v])=>((k.split('[').length>1)?(k=k.split('[')[0],(!o[k])?{...o,[k]:[v]}:{...o,[k]:[...o[k],v]}):{...o,[k]:v}),{}); 
  • An extension of a PHP form that supports multi-level arrays.

Since the last time I wrote the previous second case, at work there was a case when the PHP form has checkboxes at several levels. I wrote a new case to support the previous case and this one. I created a snippet to better demonstrate this case, show the result on the console for this demonstration, change it according to your needs. Trying to optimize it as best as possible without sacrificing performance, however, this degrades readability. The advantage is that arrays are objects, and variables that point to arrays are stored as references. You don’t need to be my guest.

 let nosubmit = (e) => { e.preventDefault(); const f = Array.from(new FormData(e.target)); const obj = f.reduce((o, [k, v]) => { let a = v, b, i, m = k.split('['), n = m[0], l = m.length; if (l > 1) { a = b = o[n] || []; for (i = 1; i < l; i++) { m[i] = (m[i].split(']')[0] || b.length) * 1; b = b[m[i]] = ((i + 1) == l) ? v : b[m[i]] || []; } } return { ...o, [n]: a }; }, {}); console.log(obj); } document.querySelector('#theform').addEventListener('submit', nosubmit, {capture: true}); 
 <h1>Multilevel Form</h1> <form action="#" method="POST" enctype="multipart/form-data" id="theform"> <input type="hidden" name="_id" value="93242" /> <input type="hidden" name="_fid" value="45c0ec96929bc0d39a904ab5c7af70ef" /> <label>Select: <select name="uselect"> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> </select> </label> <br /><br /> <label>Checkboxes one level:<br/> <input name="c1[]" type="checkbox" checked value="1"/>v1 <input name="c1[]" type="checkbox" checked value="2"/>v2 <input name="c1[]" type="checkbox" checked value="3"/>v3 </label> <br /><br /> <label>Checkboxes two levels:<br/> <input name="c2[0][]" type="checkbox" checked value="4"/>0 v4 <input name="c2[0][]" type="checkbox" checked value="5"/>0 v5 <input name="c2[0][]" type="checkbox" checked value="6"/>0 v6 <br/> <input name="c2[1][]" type="checkbox" checked value="7"/>1 v7 <input name="c2[1][]" type="checkbox" checked value="8"/>1 v8 <input name="c2[1][]" type="checkbox" checked value="9"/>1 v9 </label> <br /><br /> <label>Radios: <input type="radio" name="uradio" value="yes">YES <input type="radio" name="uradio" checked value="no">NO </label> <br /><br /> <input type="submit" value="Submit" /> </form> 
+5
source share

The FormData .entries method and the for of expression are not supported in IE11 and Safari.

Here is a simpler version to support Safari, Chrome, Firefox, and Edge.

 function formDataToJSON(formElement) { var formData = new FormData(formElement), convertedJSON = {}; formData.forEach(function(value, key) { convertedJSON[key] = value; }); return convertedJSON; } 

Warning: this answer does not work in IE11.
FormData does not have a forEach method in IE11.
I'm still looking for the ultimate solution to support all major browsers.

+4
source share

If you use lodash, this can be done concisely with fromPairs

 import {fromPairs} from 'lodash'; const object = fromPairs(Array.from(formData.entries())); 
+3
source share

Although the answer from @dzuc is already very good, you can use array destructuring (available in modern browsers or with Babel) to make it even more elegant:

 // original version from @dzuc const data = Array.from(formData.entries()) .reduce((memo, pair) => ({ ...memo, [pair[0]: pair[1], }), {}) // with array destructuring const data = Array.from(formData.entries()) .reduce((memo,[key, value]) => ({ ...memo, [key]: value, }), {}) 
+2
source share

You can try this

 formDataToJSON($('#form_example')); # Create a function to convert the serialize and convert the form data # to JSON # @param : $('#form_example'); # @return a JSON Stringify function formDataToJSON(form) { let obj = {}; let formData = form.serialize(); let formArray = formData.split("&"); for (inputData of formArray){ let dataTmp = inputData.split('='); obj[dataTmp[0]] = dataTmp[1]; } return JSON.stringify(obj); } 
+1
source share

If the following items meet your needs, you are in luck:

  1. You want to convert an array of arrays such as [['key','value1'], ['key2','value2'] (for example, that gives you FormData) into a key-> value object, for example {key1: 'value1', key2: 'value2'} and convert it to a JSON string.
  2. You are targeting browsers / devices with the latest ES6 interpreter or compiling something like babel.
  3. You want the tiniest way to do this.

Here is the code you need:

 const data = new FormData(document.querySelector('form')); const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{})); 

Hope this helps someone.

+1
source share

Offensive liner!

 Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {}); 

Today I found out that Firefox has support for distributing objects and restructuring the array!

+1
source share

 document.getElementById('foobar').addEventListener('submit', (e) => { e.preventDefault(); const formData = new FormData(e.target); const data = Array.from(formData.entries()).reduce((memo, pair) => ({ ...memo, [pair[0]]: pair[1], }), {}); document.getElementById('output').innerHTML = JSON.stringify(data); }); 
 <form id='foobar'> <input name='baz' /> <input type='submit' /> </form> <pre id='output'>Input some value and submit</pre> 
0
source share

Worked for me

  var myForm = document.getElementById("form"); var formData = new FormData(myForm), obj = {}; for (var entry of formData.entries()){ obj[entry[0]] = entry[1]; } console.log(obj); 
0
source share

All Articles