jquery serialize input with arrays
I made a recursive function/plugin to do exactly this:
$.fn.serializeControls = function() { var data = {}; function buildInputObject(arr, val) { if (arr.length < 1) return val; var objkey = arr[0]; if (objkey.slice(-1) == "]") { objkey = objkey.slice(0,-1); } var result = {}; if (arr.length == 1){ result[objkey] = val; } else { arr.shift(); var nestedVal = buildInputObject(arr,val); result[objkey] = nestedVal; } return result; } $.each(this.serializeArray(), function() { var val = this.value; var c = this.name.split("["); var a = buildInputObject(c, val); $.extend(true, data, a); }); return data;}$("#output").html(JSON.stringify($('#myform').serializeControls(), null, 2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><form id="myform" action="" method=""> <input type="text" name="name[1][first]" value="beep"> <input type="text" name="name[1][second]" value="bloop"> <input type="text" name="name[2][first]" value="derp"> <input type="text" name="foo" value="bar"> </form><pre id="output"></pre>
You can also call it on other selectors besides the entire form
. For example, calling:
$('input[name^="name\\["]').serializeControls()
will return an object containing only the name
fields. See http://codepen.io/alexweissman/pen/MyWZdN for more examples.
Please note that (for now), this will not work for field names with empty brackets (for example, fields like input name="potatoes[]"
will be ignored because a unique key cannot be extracted).
Here is a version of alexw code that works for field names with empty brackets. This allow you to manage fields with multiple values (checkboxes, select multiple).
$j.fn.serializeObject = function() { var data = {}; function buildInputObject(arr, val) { if (arr.length < 1) { return val; } var objkey = arr[0]; if (objkey.slice(-1) == "]") { objkey = objkey.slice(0,-1); } var result = {}; if (arr.length == 1){ result[objkey] = val; } else { arr.shift(); var nestedVal = buildInputObject(arr,val); result[objkey] = nestedVal; } return result; } function gatherMultipleValues( that ) { var final_array = []; $j.each(that.serializeArray(), function( key, field ) { // Copy normal fields to final array without changes if( field.name.indexOf('[]') < 0 ){ final_array.push( field ); return true; // That's it, jump to next iteration } // Remove "[]" from the field name var field_name = field.name.split('[]')[0]; // Add the field value in its array of values var has_value = false; $j.each( final_array, function( final_key, final_field ){ if( final_field.name === field_name ) { has_value = true; final_array[ final_key ][ 'value' ].push( field.value ); } }); // If it doesn't exist yet, create the field's array of values if( ! has_value ) { final_array.push( { 'name': field_name, 'value': [ field.value ] } ); } }); return final_array; } // Manage fields allowing multiple values first (they contain "[]" in their name) var final_array = gatherMultipleValues( this ); // Then, create the object $j.each(final_array, function() { var val = this.value; var c = this.name.split('['); var a = buildInputObject(c, val); $j.extend(true, data, a); }); return data;};
Given that you have successfully serialized the array to $fields
, you can now walk through it and convert it into a more easily digestable result object:
var result = {};for(var i in $fields) { var parts = $fields[i].name.split("["); var resultIndex = parseInt(parts[1].replace(']', ''), 10); result[resultIndex] = $fields[i].value; }
While $fields
is a valid name for a global variable, I can't bare to keep silent on this matter: in JavaScript, local variables are defined with var
keyword and they don't have dollar sign before them - dollar sign usually refers to jQuery object. As a result you can fetch the fields by invoking:
var fields = $('#myform').serializeArray();