Comment convertir un objet HTML5 FormData en JSON? Sans Jquery et la gestion des propriétés imbriquées dans FormData comme un objet.
Vous pouvez également utiliser forEach
sur l'objet FormData
directement:
var object = {};
formData.forEach(function(value, key){
object[key] = value;
});
var json = JSON.stringify(object);
Voici une façon de le faire dans un style plus fonctionnel, sans utiliser de bibliothèque.
Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
Exemple:
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>
Si vous avez plusieurs entrées avec le même nom, par exemple si vous utilisez <SELECT multiple>
ou si vous avez plusieurs <INPUT type="checkbox">
avec le même nom, vous devez vous en occuper et en faire un tableau. Sinon, vous n'obtenez que la dernière valeur sélectionnée.
Voici la variante moderne de l'ES6:
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's 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 );
}
Code légèrement plus ancien (mais toujours pas pris en charge par IE11, car il ne prend pas en charge ForEach
ou entries
sur 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's 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 );
}
Fonction facile à utiliser
J'ai créé Une fonction pour cela
function FormDataToJSON(FormElement){
var formData = new FormData(FormElement);
var ConvertedJSON= {};
for (const [key, value] of formData.entries())
{
ConvertedJSON[key] = value;
}
return ConvertedJSON
}
Exemple d'utilisation
var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)
Dans ce code, j'ai créé une variable JSON vide à l'aide de la boucle for
. J'ai utilisé key
s à partir d'objet formData en clés JSON dans chaque itération.
Vous trouvez ce code dans ma bibliothèque JS sur GitHub Suggérez-le-moi si cela doit être amélioré J'ai placé le code ici https://github.com/alijamal14/Utilities/blob/master/Utilities.js
Vous pouvez y parvenir en utilisant FormData () object. Cet objet FormData sera rempli avec les clés/valeurs actuelles du formulaire à l'aide de la propriété name de chaque élément pour les clés et de leur valeur soumise pour les valeurs. Il va également encoder le contenu d'entrée du fichier.
Exemple:
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);
});
La méthode FormData .entries
et l'expression for of
n'est pas prise en charge dans IE11 et Safari.
Voici une version plus simple pour supporter Safari, Chrome, Firefox et Edge
function formDataToJSON(formElement) {
var formData = new FormData(formElement),
convertedJSON = {};
formData.forEach(function(value, key) {
convertedJSON[key] = value;
});
return convertedJSON;
}
Attention: cette réponse ne fonctionne pas dans IE11.
FormData n'a pas de méthode forEach
dans IE11.
Je suis toujours à la recherche d'une solution finale pour prendre en charge tous les principaux navigateurs.
Si vous utilisez le lodash, vous pouvez le faire de manière concise avec fromPairs
import {fromPairs} from 'lodash';
const object = fromPairs(Array.from(formData.entries()));
Même si la réponse de @dzuc est déjà très bonne, vous pouvez utiliser un tableau de déstructuration (disponible dans les navigateurs modernes ou avec Babel) pour le rendre encore plus élégant:
// 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,
}), {})
Ce message a déjà un an ... mais, j’aime vraiment, vraiment, la réponse de l’ES6 @dzuc. Cependant, il est incomplet car il n'a pas été en mesure de gérer plusieurs sélections ou cases à cocher. Cela a déjà été fait et des solutions de code ont été proposées. Je les trouve lourdes et non optimisées. J'ai donc écrit deux versions basées sur @dzuc pour gérer ces cas:
let r=Array.from(fd).reduce(
(o , [k,v]) => (
(!o[k])
? {...o , [k] : v}
: {...o , [k] : [...o[k] , v]}
)
,{}
);
let obj=JSON.stringify(r);
Version Hotshot à une ligne:
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
[]
.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);
Version Hotshot à une ligne:
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}),{});
Depuis la dernière fois que j'ai écrit le deuxième cas précédent, au travail, il est apparu que le formulaire PHP avait des cases à cocher sur plusieurs niveaux. J'ai écrit un nouveau cas pour soutenir le cas précédent et celui-ci. J'ai créé un extrait pour mieux présenter ce cas, le résultat affiché sur la console de cette démo, modifiez-le selon vos besoins. J'ai essayé de l'optimiser du mieux que je pouvais sans compromettre les performances, mais cela a compromis la lisibilité humaine. Il est avantageux que les tableaux soient des objets et que les variables pointant sur des tableaux soient conservées à titre de référence. Pas de choix pour celui-ci, soyez mon invité.
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>
Si les éléments suivants répondent à vos besoins, vous avez de la chance:
[['key','value1'], ['key2','value2']
(comme ce que FormData vous donne) en un objet clé-> valeur tel que {key1: 'value1', key2: 'value2'}
et le convertir en chaîne JSON.Voici le code dont vous aurez besoin:
const data = new FormData(document.querySelector('form'));
const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{}));
J'espère que ça aide quelqu'un.
Tu peux essayer ça
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);
}
Un seul paquebot abusif!
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});
Aujourd'hui, j'ai appris que firefox supporte la propagation des objets et la déstructuration des tableaux!