Solution that worked for me was to write my own jQuery functions $.serializeAssoc() and $.serializeObject() alternatives that could also handle multidimensional arrays from multi selection options on forms.
These two functions have their pros and cons;
I use serializeAssoc to simplify form data for direct generic value access, typically in JS Validation.
serializeObject has come in handy with multifunction forms using custom numeric key indexes, Simplifying data paring of information submitted from a complicated form set-up of multi-selection fields or forms with values built by DOM where data in a form has parent and child relationships, something serializeAssoc can't handle very well.
serializeAssoc
Following function allows length checks but presents problems with custom numeric key indexes, When submitting the array in an AJAX call it causes index padding
$.fn.serializeAssoc = function() {
var data = {};
$.each( this.serializeArray(), function( key, obj ) {
var a = obj.name.match(/(.*?)\[(.*?)\]/);
if(a !== null)
{
var subName = a[1];
var subKey = a[2];
if( !data[subName] ) {
data[subName] = [ ];
}
if (!subKey.length) {
subKey = data[subName].length;
}
if( data[subName][subKey] ) {
if( $.isArray( data[subName][subKey] ) ) {
data[subName][subKey].push( obj.value );
} else {
data[subName][subKey] = [ ];
data[subName][subKey].push( obj.value );
}
} else {
data[subName][subKey] = obj.value;
}
} else {
if( data[obj.name] ) {
if( $.isArray( data[obj.name] ) ) {
data[obj.name].push( obj.value );
} else {
data[obj.name] = [ ];
data[obj.name].push( obj.value );
}
} else {
data[obj.name] = obj.value;
}
}
});
return data;
};
serializeObject
Following function below allows custom numeric indexes without causing padding but prevents length check. Check index key counts using an each loop if required. If submitting the object in an AJAX call you must first use JSON.Stringify and pass the value in a var to be decoded server side as direct usage causes an Unexpected end of line error in some browsers.
$.fn.serializeObject = function() {
var data = {};
$.each( this.serializeArray(), function( key, obj ) {
var a = obj.name.match(/(.*?)\[(.*?)\]/);
if(a !== null)
{
var subName = new String(a[1]);
var subKey = new String(a[2]);
if( !data[subName] ) {
data[subName] = { };
data[subName].length = 0;
};
if (!subKey.length) {
subKey = data[subName].length;
}
if( data[subName][subKey] ) {
if( $.isArray( data[subName][subKey] ) ) {
data[subName][subKey].push( obj.value );
} else {
data[subName][subKey] = { };
data[subName][subKey].push( obj.value );
};
} else {
data[subName][subKey] = obj.value;
};
data[subName].length++;
} else {
var keyName = new String(obj.name);
if( data[keyName] ) {
if( $.isArray( data[keyName] ) ) {
data[keyName].push( obj.value );
} else {
data[keyName] = { };
data[keyName].push( obj.value );
};
} else {
data[keyName] = obj.value;
};
};
});
return data;
};
Usage:
Adding the function
<script>
(function($){
$.fn.serializeAssoc = function() {
... As Presented Above ...
};
$.fn.serializeObject = function() {
... As Presented Above ...
};
})(jQuery);
</script>
Sample Form
<form id="myForm">
<input type="text" name="myName" />
<select name="consoles" multiple>
<option selected>PC</option>
<option selected>XBOX 360</option>
<option selected>PS3</option>
</select>
<input type="text" name="sample[100]" value="Mario" />
<input type="text" name="sample[101]" value="Brothers" />
<input type="submit" name="submit" value="Submit" />
</form>
Using the function
<script>
(function($) {
$('#myForm').submit(function(e){
e.preventDefault();
var formData = $('#myForm').serializeAssoc();
console.log(formData);
});
})(jQuery);
</script>
Dynamic form example
<form id="myForm">
<input type="text" name="myName" value="Spuggy" />
<div id="characters">
<input type="text" name="character[]" value="Mario" />
<input type="text" name="character[]" value="Sonic" />
</div>
<div id="consoles">
<input type="text" name="console[xbox]" value="XBOX One" />
<input type="text" name="console[playstation]" value="PlayStation 4" />
</div>
<input type="submit" name="submit" value="Submit" />
</form>
<script>
(function($) {
$('#myForm').submit(function(e){
e.preventDefault();
var formData = $('#myForm').serializeAssoc();
console.log(formData);
});
})(jQuery);
</script>
Dynamic form Output
[
myName: 'Spuggy',
character: [
0: 'Mario',
1: 'Sonic'
],
console: [
'xbox': 'XBOX One',
'playstation': 'PlayStation 4'
]
]