web-dev-qa-db-fra.com

Comment convertir FormData (objet HTML5) en JSON

Comment convertir un objet HTML5 FormData en JSON? Sans Jquery et la gestion des propriétés imbriquées dans FormData comme un objet.

28
Leonardo Villela

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);
58
Wilt

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>

12
dzuc

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 );
  }
7
some

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é keys à 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

5
Ali Jamal

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);

});
5
GiriB

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.

3
Tomas Prado

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()));
2
Erik van Velzen

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,
  }), {})
2
Jerry

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:

  • Pour les formes de style ASP où plusieurs noms d’éléments pourraient simplement être répétés.
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]}),{});
  • Pour les formulaires de style PHP où les noms d’éléments multiples doivent porter un suffixe [].
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}),{});
  • Extension de la forme PHP qui prend en charge les tableaux multi-niveaux.

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>

2
Carlos H.

Si les éléments suivants répondent à vos besoins, vous avez de la chance:

  1. Vous voulez convertir un tableau de tableaux comme [['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.
  2. Vous ciblez les navigateurs/appareils avec le dernier interpréteur ES6 ou compilez avec quelque chose comme Babel.
  3. Vous voulez le plus petit moyen d'y parvenir.

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.

0
KyleFarris

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);
}
0
Ivan Fretes

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!

0
nackjicholson