Converti i dati del modulo in object JavaScript con jQuery

Come posso convertire tutti gli elementi del mio modulo in un object JavaScript?

Mi piacerebbe avere un modo per build automaticamente un object JavaScript dal mio modulo, senza dover ricorrere ad ogni elemento. Non voglio una stringa, come restituito da $('#formid').serialize(); , né voglio la mappa restituita da $('#formid').serializeArray();

serializeArray già fa esattamente questo. Hai solo bisogno di massaggiare i dati nel formato richiesto:

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

Fai attenzione ai campi nascosti che hanno lo stesso nome degli ingressi reali che verranno sovrascritti.

Converti moduli in JSON COME UN BOSS


La fonte attuale è su GitHub e bower.

$ bower installa jquery-serialize-object


Il seguente codice è ora deprecato .

Il seguente codice può funzionare con tutti i tipi di nomi di input; e gestirli proprio come ci si aspetterebbe.

Per esempio:

         
 // 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" } } } } } } 

uso

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

The Sorcery (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); 

Cosa c’è di sbagliato:

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

Una versione fissa della soluzione di Tobias Cohen. Questo gestisce correttamente i valori di falsy come 0 e '' .

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

E una versione di CoffeeScript per la convenienza della codifica:

 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 

Mi piace usare Array.prototype.reduce perché è un one-liner e non si basa su Underscore.js o simili:

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

Questo è simile alla risposta usando Array.prototype.map , ma non è necessario ingombrare l’ambito con una variabile object aggiuntiva. Shopping unico.

NOTA IMPORTANTE : i moduli con input che hanno attributi di name duplicati sono HTML validi ed è in realtà un approccio comune. In questo caso, l’utilizzo di una delle risposte in questo thread non è appropriato (poiché le chiavi degli oggetti devono essere univoche).

Tutte queste risposte mi sembravano così esagerate. C’è qualcosa da dire per semplicità. Fintanto che tutti gli input dei moduli hanno l’attributo name impostato, dovrebbe funzionare solo 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.stringify?) }); 

Se stai usando Underscore.js puoi usare la relativamente concisa:

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

Non c’è davvero modo di farlo senza esaminare ciascuno degli elementi. Quello che vuoi veramente sapere è “qualcun altro ha già scritto un metodo che converte un modulo in un object JSON?” Qualcosa come il seguente dovrebbe funzionare – nota che ti fornirà solo gli elementi del modulo che verrebbero restituiti tramite un POST (deve avere un nome). Questo non è testato .

 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, so che questo ha già una risposta molto pubblicizzata, ma un’altra domanda simile è stata posta di recente, e anch’io sono stato indirizzato a questa domanda. Mi piacerebbe anche offrire la mia soluzione, perché offre un vantaggio rispetto alla soluzione accettata: puoi includere elementi del modulo disabilitati (che a volte sono importanti, a seconda di come funzioni l’interfaccia utente)

Ecco la mia risposta dall’altra domanda SO :

Inizialmente, stavamo usando il metodo serializeArray() di jQuery, ma questo non include gli elementi del modulo che sono disabilitati. Disattiveremo spesso elementi di forma “sincronizzati” con altre fonti nella pagina, ma dobbiamo comunque includere i dati nel nostro object serializzato. Quindi serializeArray() è fuori. Abbiamo utilizzato il :input selettore di :input per ottenere tutti gli elementi di input (abilitati e disabilitati) in un determinato contenitore e quindi $.map() per creare il nostro object.

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

Nota che per far funzionare tutto questo, ciascuno dei tuoi input avrà bisogno di un attributo name , che sarà il nome della proprietà dell’object risultante.

Questo è in realtà leggermente modificato da quello che abbiamo usato. Avevamo bisogno di creare un object strutturato come un IDictionary .NET, così abbiamo usato questo: (lo fornisco qui se è utile)

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

Mi piacciono entrambe queste soluzioni, perché sono semplici utilizzi della funzione $.map() e hai il controllo completo sul tuo selettore (quindi, quali elementi finirai includendo nell’object risultante). Inoltre, non è richiesto alcun plugin aggiuntivo. Plain old jQuery.

Questa funzione dovrebbe gestire array multidimensionali insieme a più elementi con lo stesso nome.

Lo sto usando da un paio d’anni finora:

 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 

Puoi farlo:

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

Vedi JSON .

Uso:

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

Produzione:

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

One-liner (nessuna dipendenza diversa da jQuery), utilizza l’associazione di oggetti fissi per la funzione passata al metodo map .

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

Cosa fa?

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

adatto per applicazioni web progressive (si può facilmente supportare sia l’invio di moduli regolari sia le richieste di ajax)

Con tutta la risposta data c’è qualche problema che è …

Se il nome dell’input è come name[key] dell’array, ma verrà generato in questo modo

  name:{ key : value } 

Ad esempio: se ho una forma come questa.

  

Quindi genererà object come questo con tutta la risposta data.

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

Ma deve generare come di seguito, qualcuno vuole ottenere come questo come di seguito.

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

Quindi prova questo sotto il codice 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 semplicità è la migliore qui. Ho usato una semplice stringa di sostituzione con un’espressione regolare, e hanno funzionato come un fascino fino ad ora. Non sono un’esperta di espressioni regolari, ma scommetto che puoi persino popolare oggetti molto complessi.

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

Usando la soluzione di maček , l’ho modificata per funzionare con il modo in cui ASP.NET MVC gestisce i propri oggetti nidificati / complessi sullo stesso modulo. Tutto quello che devi fare è modificare il pezzo valido su questo:

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

Questo corrisponderà e quindi mapperà correttamente gli elementi con nomi come:

  

E

  

Da qualche vecchia risposta:

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

il modo più semplice e accurato che ho trovato per questo problema era quello di usare il plugin bbq o questo (che è circa 0.5K di dimensione byte).

Funziona anche con array multidimensionali.

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

Ho trovato un problema con il codice di Tobias Cohen (non ho abbastanza punti per commentare direttamente), che altrimenti funziona per me. Se hai due opzioni di selezione con lo stesso nome, entrambe con valore = “”, il codice originale produrrà “nome”: “” invece di “nome”: [“”, “”]

Penso che questo possa essere corretto aggiungendo “|| o [this.name] == ‘” “alla prima condizione if:

 $.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; }; 

Se stai provando a convertire tutti i campi modulo in JSON per inviare questo modulo tramite Ajax, ecco un plugin per modulo jQuery che lo fa.

C’è un plugin per fare proprio questo per jQuery, jquery.serializeJSON . L’ho usato con successo su alcuni progetti ora. Esso funziona magicamente.

Preferisco questo approccio perché: non devi iterare più di 2 raccolte, puoi ottenere cose diverse da “nome” e “valore” se necessario, e puoi disinfettare i tuoi valori prima di memorizzarli nell’object ( se si dispone di valori predefiniti che non si desidera memorizzare, ad esempio).

 $.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; } 

Utilizzare in questo modo:

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

Testato solo su Firefox.

Trasforma qualsiasi cosa in un object (non unità testata)

  

L'output del test:

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

sopra

 

produrrà:

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

Ho trovato un problema con la soluzione selezionata.

Quando si utilizzano moduli con nomi basati su array, la funzione jQuery serializeArray () in realtà muore.

Ho un framework PHP che utilizza nomi di campi basati su array per consentire di inserire lo stesso modulo sulla stessa pagina più volte in più viste. Questo può essere utile per aggiungere, modificare ed eliminare sulla stessa pagina senza modelli di moduli in conflitto.

Dato che volevo seralizzare i moduli senza dover utilizzare questa funzionalità di base assoluta, ho deciso di scrivere il mio 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; } }); 

Nota: questo funziona anche al di fuori del modulo submit (), quindi se si verifica un errore nel resto del codice il modulo non verrà inviato se si inserisce un pulsante di collegamento che dice “salva le modifiche”.

Si noti inoltre che questa funzione non deve mai essere utilizzata per convalidare il modulo solo per raccogliere i dati da inviare al lato server per la convalida. L’utilizzo di un codice così debole e assegnato dalla massa causerà XSS , ecc.

Ho avuto lo stesso problema ultimamente e sono uscito con questo plugin jQuery .toJSON che converte un modulo in un object JSON con la stessa struttura. Questo è anche particolarmente utile per i moduli generati dynamicmente in cui si desidera consentire all’utente di aggiungere più campi in posizioni specifiche.

Il punto è che potresti voler build un modulo in modo che abbia una struttura stessa, quindi diciamo che vuoi creare un modulo in cui l’utente inserisce i suoi luoghi preferiti in città: puoi immaginare questo modulo per rappresentare un ... XML element containing a list of places the user likes thus a list of ... elements each one containing for example a ... element, a ... 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 retrive a correctly nested array you can then semantically manipulate
  • Use some server-side script to convert it into a well-formsd 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-formsd 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 retrive dynamically generated forms data.

Spero che questo aiuti qualcuno!

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 astring App.stringify( {data:App.toJson( ‘#cropform :input’ )} )

For the stringify 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.

Dato:

 

Running:

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

produce:

 {"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.stringify($('#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.stringify(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.substring(0, json.length - 1) + "}"; // do something with json return false; });