Convert form data to JavaScript object with jQuery

How do I convert all elements of my form to a JavaScript object?

I’d like to have some way of automatically building a JavaScript object from my form, without having to loop over each element. I do not want a string, as returned by $('#formid').serialize();, nor do I want the map returned by $('#formid').serializeArray();

serializeArray already does exactly that. You just need to massage the data into your required format:

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;

Watch out for hidden fields which have the same name as real inputs as they will get overwritten.

Convert forms to JSON like a boss

The current source is on GitHub and Bower.

$ bower install jquery-serialize-object

The following code is now deprecated.

The following code can take work with all sorts of input names; and handle them just as you’d expect.

For example:

<!-- All of these will work! -->
<input name="honey[badger]" value="a">
<input name="wombat[]" value="b">
<input name="hello[panda][]" value="c">
<input name="animals[0][name]" value="d">
<input name="animals[0][breed]" value="e">
<input name="crazy[1][][wonky]" value="f">
<input name="dream[as][vividly][as][you][can]" value="g">
// Output



The Sorcery (JavaScript)

    $.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_]+$/
 = 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

            var k,
                keys =,
                merge = this.value,
                reverse_key =;

            while((k = keys.pop()) !== undefined){

                // Adjust reverse_key
                reverse_key = reverse_key.replace(new RegExp("\[" + k + "\]$"), '');

                // Push
                    merge =[], self.push_counter(reverse_key), merge);

                // Fixed
                else if(k.match(patterns.fixed)){
                    merge =[], k, merge);

                // Named
                else if(k.match(patterns.named)){
                    merge ={}, k, merge);

            json = $.extend(true, json, merge);

        return json;

What’s wrong with:

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

A fixed version of Tobias Cohen’s solution. This one correctly handles falsy values like 0 and ''.

jQuery.fn.serializeObject = function() {
  var arrayData, objectData;
  arrayData = this.serializeArray();
  objectData = {};

  $.each(arrayData, function() {
    var value;

    if (this.value != null) {
      value = this.value;
    } else {

    if (objectData[] != null) {
      if (!objectData[].push) {
        objectData[] = [objectData[]];

    } else {
      objectData[] = value;

  return objectData;

And a CoffeeScript version for your coding convenience:

jQuery.fn.serializeObject = ->
  arrayData = @serializeArray()
  objectData = {}

  $.each arrayData, ->
    if @value?
      value = @value

    if objectData[@name]?
      unless objectData[@name].push
        objectData[@name] = [objectData[@name]]

      objectData[@name].push value
      objectData[@name] = value

  return objectData

I like using Array.prototype.reduce because it’s a one-liner, and it doesn’t rely on Underscore.js or the like:

    .reduce(function(a, x) { a[] = x.value; return a; }, {});

This is similar to the answer using, but you don’t need to clutter up your scope with an additional object variable. One-stop shopping.

IMPORTANT NOTE: Forms with inputs that have duplicate name attributes are valid HTML, and is actually a common approach. Using any of the answers in this thread will be inappropriate in that case (since object keys must be unique).

All of these answers seemed so over the top to me. There’s something to be said for simplicity. As long as all your form inputs have the name attribute set this should work just 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 (e.g. JSON.stringify?)

There really is no way to do this without examining each of the elements. What you really want to know is “has someone else already written a method that converts a form to a JSON object?” Something like the following should work — note that it will only give you the form elements that would be returned via a POST (must have a name). This is not tested.

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;

[UPDATE 2020]

With a simple oneliner in vanilla js that leverages fromEntries (as always, check browser support):

Object.fromEntries(new FormData(form))

I checked that there is a problem with all the other answers, that if the input name is as an array, such as name[key], then it should be generated like this:

name:{ key : value }

For example: If you have an HTML form similar to the one below:

    <input name="name" value="value" >
    <input name="name1[key1]" value="value1" >
    <input name="name2[key2]" value="value2" >
    <input name="name3[key3]" value="value3" >

But it should be generated just like the JSON below, and does not become an object like the following with all the other answers. So if anyone wants to bring something like the following JSON, try the JS code below.

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

$.fn.getForm2obj = function() {
  var _ = {};
  $.map(this.serializeArray(), function(n) {
    const keys =[a-zA-Z0-9_]+|(?=[])/g);
    if (keys.length > 1) {
      let tmp = _;
      pop = keys.pop();
      for (let i = 0; i < keys.length, j = keys[i]; i++) {
        tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];
      if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);
      else tmp[pop] = n.value;
    } else _[keys.pop()] = n.value;
  return _;
$('form input').change(function() {
<script src=""></script>
  <input name="name" value="value">
  <input type="checkbox" name="name1[]" value="1" checked="checked">1
  <input type="checkbox" name="name1[]" value="2">2
  <input type="checkbox" name="name1[]" value="3">3<br>
  <input type="radio" name="gender" value="male" checked="checked">male
  <input type="radio" name="gender" value="female"> female
  <input name="name2[key1]" value="value1">
  <input name="one[another][another_one]" value="value4">
  <input name="name3[1][name]" value="value4">
  <input name="name3[2][name]" value="value4">
  <input name="[]" value="value5">

If you are using Underscore.js you can use the relatively concise:

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

Ok, I know this already has a highly upvoted answer, but another similar question was asked recently, and I was directed to this question as well. I’d like to offer my solution as well, because it offers an advantage over the accepted solution: You can include disabled form elements (which is sometimes important, depending on how your UI functions)

Here is my answer from the other SO question:

Initially, we were using jQuery’s serializeArray() method, but that does not include form elements that are disabled. We will often disable form elements that are “sync’d” to other sources on the page, but we still need to include the data in our serialized object. So serializeArray() is out. We used the :input selector to get all input elements (both enabled and disabled) in a given container, and then $.map() to create our object.

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

Note that for this to work, each of your inputs will need a name attribute, which will be the name of the property of the resulting object.

That is actually slightly modified from what we used. We needed to create an object that was structured as a .NET IDictionary, so we used this: (I provide it here in case it’s useful)

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

I like both of these solutions, because they are simple uses of the $.map() function, and you have complete control over your selector (so, which elements you end up including in your resulting object). Also, no extra plugin required. Plain old jQuery.

This function should handle multidimensional arrays along with multiple elements with the same name.

I’ve been using it for a couple years so far:

jQuery.fn.serializeJSON=function() {
  var json = {};, function(n, i) {
    var _ ='[');
    if (_ > -1) {
      var o = json;
      _name =]/gi, '').split('[');
      for (var i=0, len=_name.length; i<len; i++) {
        if (i == len-1) {
          if (o[_name[i]]) {
            if (typeof o[_name[i]] == 'string') {
              o[_name[i]] = [o[_name[i]]];
          else o[_name[i]] = n.value || '';
        else o = o[_name[i]] = o[_name[i]] || {};
    else {
      if (json[] !== undefined) {
        if (!json[].push) {
          json[] = [json[]];
        json[].push(n.value || '');
      else json[] = n.value || '';      
  return json;

You can do this:

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


One-liner (no dependencies other than jQuery), uses fixed object binding for function passsed to map method.

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

What it does?

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

suitable for progressive web apps (one can easily support both regular form submit action as well as ajax requests)


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;


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

From some older answer:

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

I found a problem with Tobias Cohen’s code (I don’t have enough points to comment on it directly), which otherwise works for me. If you have two select options with the same name, both with value=””, the original code will produce “name”:”” instead of “name”:[“”,””]

I think this can fixed by adding ” || o[] == ”” to the first if condition:

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

Simplicity is best here. I’ve used a simple string replace with a regular expression, and they worked like a charm thus far. I am not a regular expression expert, but I bet you can even populate very complex objects.

var values = $(this).serialize(),
attributes = {};

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

Using maček’s solution, I modified it to work with the way ASP.NET MVC handles their nested/complex objects on the same form. All you have to do is modify the validate piece to this:

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

This will match and then correctly map elements with names like:

<input type="text" name="zooName" />


<input type="text" name="zooAnimals[0].name" />

const formData = new FormData(form);

let formDataJSON = {};

for (const [key, value] of formData.entries()) {

    formDataJSON[key] = value;

There is a plugin to do just that for jQuery, jquery.serializeJSON. I have used it successfully on a few projects now. It works like a charm.

the simplest and most accurate way i found for this problem was to use bbq plugin or this one (which is about 0.5K bytes size).

it also works with multi dimensional arrays.

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

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];
    document.querySelector('#asJSON').value = JSON.stringify(json);
  }, 1000);
<form name="userprofile" id="form">
  <p>Name <input type="text" name="firstname" value="John"/></p>
  <p>Family name <input name="lastname" value="Smith"/></p>
  <p>Work <input name="employment[name]" value="inc, Inc."/></p>
  <p>Works since <input name="employment[since]" value="2017" /></p>
  <p>Photo <input type="file" /></p>
  <p>Send <input type="submit" /></p>

JSON: <textarea id="asJSON"></textarea>


I prefer this approach because: you don’t have to iterate over 2 collections, you can get at things other than “name” and “value” if you need to, and you can sanitize your values before you store them in the object (if you have default values that you don’t wish to store, for example).

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


        else {
            o[name] = value;

    return o;

Use like so:

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

Only tested in Firefox.

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


NOT as


so the function IMO should read:

App.toJson = function( selector ) {
    var o = {};
    $.map( $( selector ), function( n,i )
        o[] = $(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 🙂

Turn anything into an object (not unit tested)

<script type="text/javascript">
string = {};

string.repeat = function(string, count)
    return new Array(count+1).join(string);

string.count = function(string)
    var count = 0;

    for (var i=1; i<arguments.length; i++)
        var results = string.match(new RegExp(arguments[i], 'g'));
        count += results ? results.length : 0;

    return count;

array = {};

array.merge = function(arr1, arr2)
    for (var i in arr2)
        if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')
            arr1[i] = array.merge(arr1[i], arr2[i]);
            arr1[i] = arr2[i]

    return arr1;

array.print = function(obj)
    var arr = [];
    $.each(obj, function(key, val) {
        var next = key + ": ";
        next += $.isPlainObject(val) ? array.print(val) : val;
        arr.push( next );

    return "{ " +  arr.join(", ") + " }";

node = {};

node.objectify = function(node, params)
    if (!params)
        params = {};

    if (!params.selector)
        params.selector = "*";

    if (!params.key)
        params.key = "name";

    if (!params.value)
        params.value = "value";

    var o = {};
    var indexes = {};

        var name = $(this).attr(params.key),
            value = $(this).attr(params.value);

        var obj = $.parseJSON("{"+name.replace(/([^[]*)/, function()
            return '"'+arguments[1]+'"';
        }).replace(/[(.*?)]/gi, function()
            if (arguments[1].length == 0)
                var index = arguments[3].substring(0, arguments[2]);
                indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;

                return ':{"'+indexes[index]+'"';
                return ':{"'+escape(arguments[1])+'"';
        })+':"'+value.replace(/[\"]/gi, function()
            return "\"+arguments[0]; 
        })+'"'+string.repeat('}', string.count(name, ']'))+"}");

        o = array.merge(o, obj);

    return o;

The output of test:

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


    <input name="input[a]" type="text" value="text"/>
    <select name="input[b]">

    <input name="otherinput[c][a]" value="a"/>
    <input name="otherinput[c][]" value="b"/>
    <input name="otherinput[d][b]" value="c"/>
    <input name="otherinput[c][]" value="d"/>

    <input type="hidden" name="anotherinput" value="hidden"/>
    <input type="hidden" name="anotherinput" value="1"/>

    <input type="submit" value="submit"/>

will yield:

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

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.


<form id="myform">
    <input type="text" name="name"/>
    <input type="text" name="email"/>
    <input type="password" name="password"/>




{"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()));

I found a problem with the selected solution.

When using forms that have array based names the jQuery serializeArray() function actually dies.

I have a PHP framework that uses array-based field names to allow for the same form to be put onto the same page multiple times in multiple views. This can be handy to put both add, edit and delete on the same page without conflicting form models.

Since I wanted to seralize the forms without having to take this absolute base functionality out I decided to write my own seralizeArray():

        var $vals = {};

        $("#video_edit_form input").each(function(i){
            var name = $(this).attr("name").replace(/editSingleForm[/i, '');

            name = name.replace(/]/i, '');

                case "text":
                    $vals[name] = $(this).val();
                case "checkbox":
                        $vals[name] = $(this).val();
                case "radio":
                        $vals[name] = $(this).val();

Please note: This also works outside of form submit() so if an error occurs in the rest of your code the form won’t submit if you place on a link button saying “save changes”.

Also note that this function should never be used to validate the form only to gather the data to send to the server-side for validation. Using such weak and mass-assigned code WILL cause XSS, etc.

I had the same problem lately and came out with this .toJSON jQuery plugin which converts a form into a JSON object with the same structure. This is also expecially useful for dynamically generated forms where you want to let your user add more fields in specific places.

The point is you may actually want to build a form so that it has a structure itself, so let’s say you want to make a form where the user inserts his favourite places in town: you can imagine this form to represent a <places>...</places> XML element containing a list of places the user likes thus a list of <place>...</place> elements each one containing for example a <name>...</name> element, a <type>...</type> element and then a list of <activity>...</activity> elements to represent the activities you can perform in such a place. So your XML structure would be like this:




        <activity>watch TV</activity>





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-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 <form> tag is the root, but then we have that <place> element which is a container and not a data element itself, so we cannot use an input tag for it.

Here’s where the <fieldset> tag comes in handy! We’ll use <fieldset> tags to represent all container elements in our form/XML representation and so getting to a result like this:

<form name="places">

    <fieldset name="place">

        <input type="text" name="name"/>
        <select name="type">
            <option value="dwelling">Dwelling</option>
            <option value="restoration">Restoration</option>
            <option value="sport">Sport</option>
            <option value="administrative">Administrative</option>

        <input type="text" name="activity"/>
        <input type="text" name="activity"/>
        <input type="text" name="activity"/>



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:




            'name': 'Home',
            'type': 'dwelling',


                 '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] || [];
        } 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 retrive dynamically generated forms data.

I hope this helps someone!

I coded a form to a multidimensional JavaScript object myself to use it in production. The result is

Leave a Comment