Convertir les données de formulaire en object JavaScript avec jQuery

Comment convertir tous les éléments de mon formulaire en un object JavaScript?

J’aimerais avoir un moyen de créer automatiquement un object JavaScript à partir de mon formulaire, sans avoir à parcourir chaque élément. Je ne veux pas de chaîne, telle que renvoyée par $('#formid').serialize(); Je ne veux pas non plus que la carte soit retournée par $('#formid').serializeArray();

serializeArray . Il vous suffit de masser les données dans le format requirejs:

 function objectiveyForm(formArray) {//serialize data function var returnArray = {}; for (var i = 0; i < formArray.length; i++){ returnArray[formArray[i]['name']] = formArray[i]['value']; } return returnArray; } 

Faites attention aux champs cachés qui portent le même nom que les entrées réelles, car ils seront écrasés.

Convertir des formulaires en JSON LIKE A BOSS


La source actuelle est sur GitHub et bower.

$ bower installe jquery-serialize-object


Le code suivant est maintenant obsolète .

Le code suivant peut fonctionner avec toutes sortes de noms d’entrée; et les manipuler comme prévu.

Par exemple:

         
 // output { "honey":{ "badger":"a" }, "wombat":["b"], "hello":{ "panda":["c"] }, "animals":[ { "name":"d", "breed":"e" } ], "crazy":[ null, [ {"wonky":"f"} ] ], "dream":{ "as":{ "vividly":{ "as":{ "you":{ "can":"g" } } } } } } 

Usage

 $('#my-form').serializeObject(); 

La sorcellerie (JavaScript)

 (function($){ $.fn.serializeObject = function(){ var self = this, json = {}, push_counters = {}, patterns = { "validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/, "key": /[a-zA-Z0-9_]+|(?=\[\])/g, "push": /^$/, "fixed": /^\d+$/, "named": /^[a-zA-Z0-9_]+$/ }; this.build = function(base, key, value){ base[key] = value; return base; }; this.push_counter = function(key){ if(push_counters[key] === undefined){ push_counters[key] = 0; } return push_counters[key]++; }; $.each($(this).serializeArray(), function(){ // skip invalid keys if(!patterns.validate.test(this.name)){ return; } var k, keys = this.name.match(patterns.key), merge = this.value, reverse_key = this.name; while((k = keys.pop()) !== undefined){ // adjust reverse_key reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), ''); // push if(k.match(patterns.push)){ merge = self.build([], self.push_counter(reverse_key), merge); } // fixed else if(k.match(patterns.fixed)){ merge = self.build([], k, merge); } // named else if(k.match(patterns.named)){ merge = self.build({}, k, merge); } } json = $.extend(true, json, merge); }); return json; }; })(jQuery); 

Quel est le problème avec:

 var data = {}; $(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 

Une version fixe de la solution de Tobias Cohen. Celui-ci gère correctement les valeurs de faux comme 0 et '' .

 jQuery.fn.serializeObject = function() { var arrayData, objectData; arrayData = this.serializeArray(); objectData = {}; $.each(arrayData, function() { var value; if (this.value != null) { value = this.value; } else { value = ''; } if (objectData[this.name] != null) { if (!objectData[this.name].push) { objectData[this.name] = [objectData[this.name]]; } objectData[this.name].push(value); } else { objectData[this.name] = value; } }); return objectData; }; 

Et une version CoffeeScript pour votre commodité de codage:

 jQuery.fn.serializeObject = -> arrayData = @serializeArray() objectData = {} $.each arrayData, -> if @value? value = @value else value = '' if objectData[@name]? unless objectData[@name].push objectData[@name] = [objectData[@name]] objectData[@name].push value else objectData[@name] = value return objectData 

J’aime utiliser Array.prototype.reduce parce que c’est un one-liner et qu’il ne repose pas sur Underscore.js ou similaire:

 $('#formid').serializeArray() .reduce(function(a, x) { a[x.name] = x.value; return a; }, {}); 

Ceci est similaire à la réponse en utilisant Array.prototype.map , mais vous n’avez pas besoin d’encombrer votre scope avec une variable d’object supplémentaire. Guichet unique.

REMARQUE IMPORTANTE : Les formulaires avec des entrées ayant des atsortingbuts de name double sont des codes HTML valides et constituent en réalité une approche commune. L’utilisation de l’une des réponses dans ce thread sera inappropriée dans ce cas (puisque les clés d’object doivent être uniques).

Toutes ces réponses me semblaient tellement exagérées. Il y a quelque chose à dire pour la simplicité. Tant que toutes les entrées de votre formulaire ont l’atsortingbut name défini, cela devrait fonctionner uniquement avec jim dandy.

 $('form.myform').submit(function () { var $this = $(this) , viewArr = $this.serializeArray() , view = {}; for (var i in viewArr) { view[viewArr[i].name] = viewArr[i].value; } //Do stuff with view object here (eg JSON.ssortingngify?) }); 

Si vous utilisez Underscore.js, vous pouvez utiliser le relativement concis:

 _.object(_.map($('#myform').serializeArray(), _.values)) 

Il n’y a vraiment aucun moyen de le faire sans examiner chacun des éléments. Ce que vous voulez vraiment savoir, c’est “quelqu’un d’autre a-t-il déjà écrit une méthode qui convertit un formulaire en object JSON?” Quelque chose comme ce qui suit devrait fonctionner – notez que cela ne vous donnera que les éléments de formulaire qui seront renvoyés via un POST (doit avoir un nom). Ceci n’est pas testé .

 function formToJSON( selector ) { var form = {}; $(selector).find(':input[name]:enabled').each( function() { var self = $(this); var name = self.attr('name'); if (form[name]) { form[name] = form[name] + ',' + self.val(); } else { form[name] = self.val(); } }); return form; } 

Ok, je sais que cette réponse a déjà été très appréciée, mais une autre question similaire a été posée récemment, et j’ai été orientée vers cette question également. Je voudrais également proposer ma solution, car elle offre un avantage par rapport à la solution acceptée: vous pouvez inclure des éléments de formulaire désactivés (ce qui est parfois important, selon les fonctions de votre interface utilisateur).

Voici ma réponse à l’ autre question de SO :

Au départ, nous utilisions la méthode serializeArray() de jQuery, mais cela n’incluait pas les éléments de formulaire désactivés. Nous allons souvent désactiver les éléments de formulaire “synchronisés” avec d’autres sources sur la page, mais nous devons toujours inclure les données dans notre object sérialisé. Ainsi, serializeArray() est sorti. Nous avons utilisé le sélecteur :input pour obtenir tous les éléments d’entrée (activés et désactivés) dans un conteneur donné, puis $.map() pour créer notre object.

 var inputs = $("#container :input"); var obj = $.map(inputs, function(n, i) { var o = {}; o[n.name] = $(n).val(); return o; }); console.log(obj); 

Notez que pour que cela fonctionne, chacune de vos entrées aura besoin d’un atsortingbut name , qui sera le nom de la propriété de l’object résultant.

Cela est en fait légèrement modifié par rapport à ce que nous avons utilisé. Nous devions créer un object structuré sous la forme d’un .NET IDictionary, nous l’avons donc utilisé: (je le fournis ici au cas où cela serait utile)

 var obj = $.map(inputs, function(n, i) { return { Key: n.name, Value: $(n).val() }; }); console.log(obj); 

J’aime ces deux solutions, car elles sont des utilisations simples de la fonction $.map() et vous avez un contrôle complet sur votre sélecteur (donc, quels éléments vous $.map() , y compris dans l’object résultant). De plus, aucun plugin supplémentaire n’est requirejs. Plain vieux jQuery.

Cette fonction doit gérer les tableaux multidimensionnels avec plusieurs éléments portant le même nom.

Je l’utilise depuis quelques années:

 jQuery.fn.serializeJSON=function() { var json = {}; jQuery.map(jQuery(this).serializeArray(), function(n, i) { var _ = n.name.indexOf('['); if (_ > -1) { var o = json; _name = n.name.replace(/\]/gi, '').split('['); for (var i=0, len=_name.length; i 

Tu peux le faire:

 var frm = $(document.myform); var data = JSON.ssortingngify(frm.serializeArray()); 

Voir JSON .

Utilisation:

 function form_to_json (selector) { var ary = $(selector).serializeArray(); var obj = {}; for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value; return obj; } 

Sortie:

 {"myfield": "myfield value", "passwordfield": "mypasswordvalue"} 

One-liner (pas de dépendances autres que jQuery), utilise la liaison d’object fixe pour la fonction transmise à la méthode map .

 $('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0] 

Ce qu’il fait?

 "id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" } 

adapté aux applications Web progressives (on peut facilement prendre en charge les actions de soumission de formulaires aussi bien que les requêtes ajax)

Avec toutes les réponses données, il y a un problème qui est …

Si vous saisissez le nom sous forme de tableau comme name[key] , mais cela générera comme ceci

  name:{ key : value } 

Par exemple: Si j’ai un formulaire comme celui-ci.

  

Ensuite, il générera un object comme celui-ci avec toutes les réponses données.

 Object { name : 'value', name1[key1] : 'value1', name2[key2] : 'value2', name3[key3] : 'value3', } 

Mais il faut générer comme ci-dessous, n’importe qui veut obtenir comme ci-dessous.

 Object { name : 'value', name1 : { key1 : 'value1' }, name2 : { key2 : 'value2' }, name3 : { key2 : 'value2' } } 

Ensuite, essayez ce code ci-dessous js.

 (function($){ $.fn.getForm2obj = function(){ var _ = {},_t=this; this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);} this.b = function(k,v,a = 0){ if(a) eval(k+".push("+v+");"); else eval(k+"="+v+";"); }; $.map(this.serializeArray(),function(n){ if(n.name.indexOf('[') > -1 ){ var keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g),le = Object.keys(keys).length,tmp = '_'; $.map(keys,function(key,i){ if(key == ''){ eval("ale = Object.keys("+tmp+").length;"); if(!ale) _t.b(tmp,'[]'); if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'",1); else _t.b(tmp += "["+ale+"]",'{}'); }else{ _t.c(tmp += "['"+key+"']",'{}'); if(le == (i+1)) _t.b(tmp,"'"+n['value']+"'"); } }); }else _t.b("_['"+n['name']+"']","'"+n['value']+"'"); }); return _; } })(jQuery); console.log($('form').getForm2obj()); 
   Convert form data to JavaScript object with jQuery   

La simplicité est la meilleure ici. J’ai utilisé une chaîne simple remplacée par une expression régulière, et elles fonctionnaient comme un charme jusqu’à présent. Je ne suis pas un expert en expression régulière, mais je parie que vous pouvez même remplir des objects très complexes.

 var values = $(this).serialize(), atsortingbutes = {}; values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) { atsortingbutes[name] = value; }); 

En utilisant la solution de maček , je l’ai modifiée pour fonctionner avec la manière dont ASP.NET MVC gère leurs objects nesteds / complexes sur le même formulaire. Tout ce que vous avez à faire est de modifier la pièce validée à ceci:

 "validate": /^[a-zA-Z][a-zA-Z0-9_]*((?:\[(?:\d*|[a-zA-Z0-9_]+)\])*(?:\.)[a-zA-Z][a-zA-Z0-9_]*)*$/, 

Cela correspondra puis mappera correctement les éléments avec des noms tels que:

  

Et

  

D’une réponse plus ancienne :

 $('form input,select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{}) 

La manière la plus simple et la plus précise que j’ai trouvée pour ce problème était d’utiliser le plugin bbq ou celui- ci (qui a une taille d’environ 0,5 Ko).

il fonctionne également avec des tableaux multidimensionnels.

 $.fn.serializeObject = function() { return $.deparam(this.serialize()); }; 

J’ai trouvé un problème avec le code de Tobias Cohen (je n’ai pas assez de points pour le commenter directement), qui fonctionne autrement pour moi. Si vous avez deux options select avec le même nom, les deux avec value = “”, le code original produira “name”: “” au lieu de “name”: [“”, “”]

Je pense que cela peut être corrigé en ajoutant “|| o [this.name] == ”” à la première condition:

 $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name] || o[this.name] == '') { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; }; 

Si vous essayez de convertir tous les champs de formulaire en JSON afin de soumettre ce formulaire via Ajax, voici un plug – in de formulaire jQuery qui le fait.

Il y a un plugin pour faire ça juste pour jQuery, jquery.serializeJSON . Je l’ai utilisé avec succès sur quelques projets maintenant. Il fonctionne comme un charme.

Je préfère cette approche car: vous n’avez pas à parcourir plus de 2 collections, vous pouvez obtenir des choses autres que “name” et “value” si nécessaire, et vous pouvez assainir vos valeurs avant de les stocker dans l’object ( si vous avez des valeurs par défaut que vous ne souhaitez pas stocker, par exemple).

 $.formObject = function($o) { var o = {}, real_value = function($field) { var val = $field.val() || ""; // additional cleaning here, if needed return val; }; if (typeof o != "object") { $o = $(o); } $(":input[name]", $o).each(function(i, field) { var $field = $(field), name = $field.attr("name"), value = real_value($field); if (o[name]) { if (!$.isArray(o[name])) { o[name] = [o[name]]; } o[name].push(value); } else { o[name] = value; } }); return o; } 

Utilisez comme ça:

 var obj = $.formObject($("#someForm")); 

Seulement testé dans Firefox.

Transformez n’importe quoi en object (non testé par l’unité)

  

La sortie de test:

 $(document).ready(function() { console.log(array.print(node.objectivey($("form"), {}))); console.log(array.print(node.objectivey($("form"), {selector: "select"}))); }); 

sur

 

va donner:

 { input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 } { input: { b: select } } 

J’ai trouvé un problème avec la solution sélectionnée.

Lorsque vous utilisez des formulaires qui ont des noms basés sur des tableaux, la fonction jQuery serializeArray () est réellement morte.

J’ai un framework PHP qui utilise des noms de champs basés sur des tableaux pour permettre à un même formulaire d’être placé sur la même page plusieurs fois dans plusieurs vues. Cela peut être pratique pour append, éditer et supprimer à la fois les modèles sans conflit.

Puisque je voulais séraliser les formulaires sans avoir à sortir cette fonctionnalité de base absolue, j’ai décidé d’écrire mon propre seralizeArray ():

  var $vals = {}; $("#video_edit_form input").each(function(i){ var name = $(this).attr("name").replace(/editSingleForm\[/i, ''); name = name.replace(/\]/i, ''); switch($(this).attr("type")){ case "text": $vals[name] = $(this).val(); break; case "checkbox": if($(this).attr("checked")){ $vals[name] = $(this).val(); } break; case "radio": if($(this).attr("checked")){ $vals[name] = $(this).val(); } break; default: break; } }); 

Veuillez noter que ceci fonctionne également en dehors du formulaire submit (), donc si une erreur survient dans le rest de votre code, le formulaire ne sera pas envoyé si vous placez un lien indiquant “Enregistrer les modifications”.

Notez également que cette fonction ne doit jamais être utilisée pour valider le formulaire uniquement pour rassembler les données à envoyer côté serveur pour validation. L’utilisation d’un code aussi faible et atsortingbué en masse causera XSS , etc.

J’ai eu le même problème récemment et est sorti avec ce plugin .toJSON jQuery qui convertit un formulaire en un object JSON avec la même structure. Ceci est également particulièrement utile pour les formulaires générés dynamicment où vous voulez laisser votre utilisateur append plus de champs à des endroits spécifiques.

Le fait est que vous pouvez réellement vouloir créer un formulaire pour qu’il ait lui-même une structure, alors supposons que vous vouliez créer un formulaire où l’utilisateur insère ses endroits préférés en ville: vous pouvez imaginer que ce formulaire représente un ... Elément XML contenant une liste de lieux que l’utilisateur aime ainsi une liste d’éléments ... chacun contenant par exemple un élément ... , un ... element and then a list of ... elements to represent the activities you can perform in such a place. So your XML structure would be like this:

   Home dwelling sleep eat watch TV  ... ...  

How cool would it be to have a JSON object out of this which would represent this exact structure so you’ll be able to either:

  • Store this object as it is in any CouchDB -like database
  • Read it from your $_POST[] server side and resortingve a correctly nested array you can then semantically manipulate
  • Use some server-side script to convert it into a well-formed XML file (even if you don’t know its exact structure a-priori)
  • Just somehow use it as it is in any Node.js -like server script

OK, so now we need to think how a form can represent an XML file.

Of course the

tag is the root , but then we have that element which is a container and not a data element itself, so we cannot use an input tag for it.

Here’s where the

tag comes in handy! We’ll use

tags to represent all container elements in our form/XML representation and so getting to a result like this:

 

As you can see in this form, we’re breaking the rule of unique names, but this is OK because they’ll be converted into an array of element thus they’ll be referenced only by their index inside the array.

At this point you can see how there’s no name="array[]" like name inside the form and everything is pretty, simple and semantic.

Now we want this form to be converted into a JSON object which will look like this:

 {'places':{ 'place':[ { 'name': 'Home', 'type': 'dwelling', 'activity':[ 'sleep', 'eat', 'watch TV' ] }, {...}, {...} ] }} 

To do this I have developed this jQuery plugin here which someone helped optimizing in this Code Review thread and looks like this:

 $.fn.toJSO = function () { var obj = {}, $kids = $(this).children('[name]'); if (!$kids.length) { return $(this).val(); } $kids.each(function () { var $el = $(this), name = $el.attr('name'); if ($el.siblings("[name=" + name + "]").length) { if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) { obj[name] = obj[name] || []; obj[name].push($el.toJSO()); } } else { obj[name] = $el.toJSO(); } }); return obj; }; 

I also made this one blog post to explain this more.

This converts everything in a form to JSON (even radio and check boxes) and all you’ll have left to do is call

 $.post('script.php',('form').toJSO(), ...); 

I know there’s plenty of ways to convert forms into JSON objects and sure .serialize() and .serializeArray() work great in most cases and are mostly intended to be used, but I think this whole idea of writing a form as an XML structure with meaningful names and converting it into a well-formed JSON object is worth the try, also the fact you can add same-name input tags without worrying is very useful if you need to resortingve dynamically generated forms data.

J’espère que ça aidera quelqu’un!

I coded a form to a multidimensional JavaScript object myself to use it in production. The result is https://github.com/serbanghita/formToObject.js .

I like samuels version, but I believe it has a small error. Normally JSON is sent as

{“coreSKU”:”PCGUYJS”,”name_de”:”whatever”,…

NOT as

[{“coreSKU”:”PCGUYJS”},{“name_de”:”whatever”},…

so the function IMO should read:

 App.toJson = function( selector ) { var o = {}; $.map( $( selector ), function( n,i ) { o[n.name] = $(n).val(); }); return o; } 

and to wrap it in data array (as commonly expected, too), and finally send it as assortingng App.ssortingngify( {data:App.toJson( ‘#cropform :input’ )} )

For the ssortingngify look at Question 3593046 for the lean version, at json2.js for the every-eventuality-covered version. That should cover it all 🙂

For a quick, modern solution, use the JSONify jQuery plugin. The example below is taken verbatim from the GitHub README. All credit to Kushal Pandya, author of the plugin.

Donné:

 

Running:

 $('#myform').jsonify(); 

Produit:

 {"name":"Joe User","email":"[email protected]","password":"mypass"} 

If you want to do a jQuery POST with this JSON object:

 $('#mybutton').click(function() { $.post('/api/user', JSON.ssortingngify($('#myform').jsonify())); } 

Another answer

 document.addEventListener("DOMContentLoaded", function() { setInterval(function() { var form = document.getElementById('form') || document.querySelector('form[name="userprofile"]'); var json = Array.from(new FormData(form)).map(function(e,i) {this[e[0]]=e[1]; return this;}.bind({}))[0]; console.log(json) document.querySelector('#asJSON').value = JSON.ssortingngify(json); }, 1000); }) 
 

Name

Family name

Work

Works since

Photo

Send

JSON:

I wouldn’t use this on a live site due to XSS attacks and probably plenty of other issues, but here’s a quick example of what you could do:

 $("#myform").submit(function(){ var arr = $(this).serializeArray(); var json = ""; jQuery.each(arr, function(){ jQuery.each(this, function(i, val){ if (i=="name") { json += '"' + val + '":'; } else if (i=="value") { json += '"' + val.replace(/"/g, '\\"') + '",'; } }); }); json = "{" + json.subssortingng(0, json.length - 1) + "}"; // do something with json return false; });