Jquery serializes input with arrays
I have a form on my website:
<form id="myform" action="" method=""> <input type="text" name="name[1][first]"> <input type="text" name="name[2][first]"> <input type="text" name="name[3][first]"> </form> I want to just grab all the data and send it to the web service, so this is js:
$fields = $('#myform').serializeArray(); The problem is that it creates json with all the brackets specified in the input names, so I get a parsing error.
How can I use serializeArray and get the correct json?
The resulting format, which I would like to see, looks something like this:
{ "name": { "1": { "first": "val1" }, "2": { "first": "val2" }, "3": { "first": "val3" } } } Thanks!
I made a recursive function / plugin to do just that:
$.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 whole form . For example, calling:
$('input[name^="name\\["]').serializeControls()
returns an object containing only name fields. See http://codepen.io/alexweissman/pen/MyWZdN for details.
Please note that (for now) this will not work for field names with empty brackets (for example, fields such as input name="potatoes[]" will be ignored because the unique key cannot be extracted).
Given that you have successfully serialized the array to $fields , you can go through it and convert it to a more easily digestible 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; } As long as $fields is a valid name for a global variable, I can't keep silent about this: in JavaScript, local variables are defined with the var keyword and there is no dollar sign in front of them - the dollar sign usually refers to a jQuery object. As a result, you can get the fields by calling:
var fields = $('#myform').serializeArray(); Here is the version of alexw code that works for field names with empty brackets . This allows 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 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 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; };