Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

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

share|improve this question
11  
because the first returns a string, exactly like what you'd get if you submitted the form with a GET method, and the second gives you a array of objects, each with a name value pair. I want that if i have a field named "email" i get an object that will allow me to retrieve that value with obj.email. With serializeArray(), i'd have to do something like obj[indexOfElement].value – Yisroel Jul 26 '09 at 14:05
2  
@James - The accepted answer using D. Crockford's JSON-js library. Here's an example: github.com/tleese22/google-app-engine-jappstart/blob/master/src/… – Taylor Leese Dec 22 '10 at 20:11
2  
@Taylor Yes, I'd say the correct answer uses Crockford's lib and Tobias' function like so: JSON.stringify($('myForm').serializeObject()) – James McCormack Dec 23 '10 at 12:30
3  
@Jonz - There are other reasons besides submission/transmission for using a form element. If you're doing any heavy lifting with the form values within JavaScript (e.g. single page app), it's very handy to have them in an object format for accessing & manipulating. Also, HTTP Post and Get query strings aren't the only formats for moving data around. – Patrick M Jul 9 '12 at 14:11
2  
A good js I came across >> github.com/marioizquierdo/jquery.serializeJSON – Bongs Mar 2 '13 at 21:56

43 Answers 43

up vote 1094 down vote accepted

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

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            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;
};

Example of this in action: Fiddle

share|improve this answer
4  
as tvanfosson says, why iterate over the collection twice? – Yisroel Jul 27 '09 at 16:15
42  
Do you mean "why use serializeArray to get the data in the first place?" Because serializeArray is already written, is unit tested in multiple browsers, and could theoretically be improved in later versions of jQuery. The less code you write that has to access inconsistent things like DOM elements directly, the more stable your code will be. – Tobias Cohen Jul 28 '09 at 3:05
29  
Be warned, serializeArray() will not include disabled elements. I often disable input elements that are sync'd to other elements on the page, but I still want them included in my serialized object. You're better off using something like $.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } ); if you need to include disabled elements. – Samuel Meacham Jul 18 '10 at 23:54
14  
@TobiasCohen It doesn't handle foo[bar]-type inputs as expected, not to mention most of the other input name varieties. After being very frustrated with shallow solutions to this problem, I ended up writing my own jQuery plugin -- details in the answer I provided to this question. – maček Dec 7 '11 at 20:13
4  
@macek I know this is a few months old, but since when did do arrays use non-numeric indexes? No one should name an input foo[bar] and hope to treat it as an array. Are you confusing arrays and hashes? Yes, [] is commonly understood to be an accessor but not just for arrays. Also saying it's valid HTML but not in the HTML spec is a contradiction. Yes, the browser may not choke on it, but not many webservers are going to know how to deserialize that like they would an array. Why? Because its not in the HTML spec. Therefore, it is indeed invalid. – Kroehre Sep 8 '12 at 8:29

you can simply use javascript function

 JSON.parse('{ "employees" : [' +
 '{ "firstName":"John" , "lastName":"Doe" },' +
 '{ "firstName":"Anna" , "lastName":"Smith" },' +
 '{ "firstName":"Peter" , "lastName":"Jones" } ]}');
share|improve this answer

I don't know why, but I found only one really working solution for form with inputs with names like name="some[sub][sub][sub][name]".

There is it: LINK

share|improve this answer

Here's a non-jQuery way:

    var getFormData = function(form) {
        //Ignore the submit button
        var elements = Array.prototype.filter.call(form.elements, function(element) {
            var type = element.getAttribute('type');
            return !type || type.toLowerCase() !== 'submit';
        });

You can use it like this:

function() {

    var getFormData = function(form) {
        //Ignore the submit button
        var elements = Array.prototype.filter.call(form.elements, function(element) {
            var type = element.getAttribute('type');
            return !type || type.toLowerCase() !== 'submit';
        });

        //Make an object out of the form data: {name: value}
        var data = elements.reduce(function(data, element) {
            data[element.name] = element.value;
            return data;
        }, {});

        return data;
    };

    var post = function(action, data, callback) {
        var request = new XMLHttpRequest();
        request.onload = callback;
        request.open('post', action);
        request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
        request.send(JSON.stringify(data), true);
        request.send();
    };

    var submit = function(e) {
        e.preventDefault();
        var form = e.target;
        var action = form.action;
        var data = getFormData(form);
        //change the third argument in order to do something
        //more intersting with the response than just print it
        post(action, data, console.log.bind(console));
    }

    //change formName below
    document.formName.onsubmit = submit;

})();
share|improve this answer

From some older answer:

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

If you want to convert a form to a javascript object, then the easiest solution (at this time) is to use jQuery's each and serializeArray function-methods.

$.fn.serializeObject = function() {

  var form = {};
  $.each($(this).serializeArray(), function (i, field) {
    form[field.name] = field.value || "";
  });

  return form;
};

Plugin hosted on GitHub:
https://github.com/tfmontague/form-object/blob/master/README.md

Can be installed with Bower:
bower install git://github.com/tfmontague/form-object.git

share|improve this answer

I recently had the same problem so I developed a function that allows parsing a form's controls to obtain control id/value and convert that to JSON.

It is flexible enough to allow adding more controls. You just need to specify the control type and the attribute that you want to interpreted as value.

You can find the full script here.

The advantage is that it only takes the data you actually need, without dragging the whole object.

The dissadvantage is that if you have nested options, you need to prefix the IDs accordingly so you can use a duplicate option to its specific group.

I hope this helps!

share|improve this answer

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

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

This is similar to the answer using Array.prototype.map, 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).

share|improve this answer
1  
True, but it's easy enough to polyfill. Also, the IE8 headache is almost over, thanks to Microsoft's great work with IE11 Enterprise Mode -- I no longer cater to individual users with IE8, but when an organization with 10,000 employees that all use IE8 comes along...that's different. Fortunately, Microsoft is working hard on that problem. – Ethan Brown Mar 12 at 15:16
3  
I work for that 10,000 employee organization. – gfullam Mar 12 at 15:18

If you are sending a form with JSON you must remove [] in sending the string. You can do that with the jQuery function serializeObject():

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

$.fn.serializeObject = function() {
    var o = {};
    //var a = this.serializeArray();
    $(this).find('input[type="hidden"], input[type="text"], input[type="password"], input[type="checkbox"]:checked, input[type="radio"]:checked, select').each(function() {
        if ($(this).attr('type') == 'hidden') { //If checkbox is checked do not take the hidden field
            var $parent = $(this).parent();
            var $chb = $parent.find('input[type="checkbox"][name="' + this.name.replace(/\[/g, '\[').replace(/\]/g, '\]') + '"]');
            if ($chb != null) {
                if ($chb.prop('checked')) return;
            }
        }
        if (this.name === null || this.name === undefined || this.name === '')
            return;
        var elemValue = null;
        if ($(this).is('select'))
            elemValue = $(this).find('option:selected').val();
        else
            elemValue = this.value;
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(elemValue || '');
        }
        else {
            o[this.name] = elemValue || '';
        }
    });
    return o;
}
share|improve this answer

You can do this:

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

See JSON in JavaScript.

share|improve this answer

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.

share|improve this answer

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

_.object(_.map($('#myform').serializeArray(), _.values))
share|improve this answer
1  
Exactly what I was looking for. Thanks! – GeorgeMillo Feb 20 '14 at 3:15

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

And

<input type="text" name="zooAnimals[0].name" />
share|improve this answer

Use:

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

Output:

{"myfield": "myfield value", "passwordfield": "mypasswordvalue"}
share|improve this answer

I wrote a jQuery module, jsForm, that can do this bidirectional even for quite complicated forms (allows collections and other more complex structures as well).

It uses the name of the fields (plus a few special classes for collections) and matches a JSON object. It allows automatic replication of DOM-elements for collections and data handling:

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="https://raw.github.com/corinis/jsForm/master/src/jquery.jsForm.js"></script>
        <script>
        $(function(){
            // Some JSON data
            var jsonData = {
                name: "TestName",   // Standard inputs
                description: "long Description\nMultiline", // Textarea
                links: [{href:'http://stackoverflow.com',description:'StackOverflow'}, {href:'http://www.github.com', description:'GitHub'}],   // Lists
                active: true,   // Checkbox
                state: "VISIBLE"    // Selects (enums)
            };

            // Initialize the form, prefix is optional and defaults to data
            $("#details").jsForm({
                data:jsonData
            });

            $("#show").click(function() {
                // Show the JSON data
                alert(JSON.stringify($("#details").jsForm("get"), null, " "));
            });
        });
        </script>
    </head>
    <body>
        <h1>Simpel Form Test</h1>
        <div id="details">
            Name: <input name="data.name"/><br/>
            <input type="checkbox" name="data.active"/> active<br/>
            <textarea name="data.description"></textarea><br/>
            <select name="data.state">
                <option value="VISIBLE">visible</option>
                <option value="IMPORTANT">important</option>
                <option value="HIDDEN">hidden</option>
            </select>
            <fieldset>
                <legend>Links</legend>
                <ul class="collection" data-field="data.links">
                    <li><span class="field">links.description</span> Link: <input name="links.href"/> <button class="delete">x</button></li>
                </ul>
            </fieldset>
            <button class="add" data-field="data.links">add a link</button><br/>
            Additional field: <input name="data.addedField"/>
        </div>
        <button id="show">Show Object</button>
    </body>
</html>
share|improve this answer

I coded a form to a multidimensional JavaScript object myself to use it in production. The result is https://github.com/serbanghita/formToObject.js.

share|improve this answer

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;
});
share|improve this answer

Use this:

var sf = $('#mainForm').serialize(); // URL encoded string
sf = sf.replace(/"/g, '\"');         // Be sure all "s are escaped
sf = '{"' + sf.replace(/&/g, '","'); // Start "object", replace tupel delimiter &
sf = sf.replace(/=/g, '":"') + '"}'; // Replace equal sign, add closing "object"

// Test the "object"
var formdata = eval("(" + sf + ")"); 
console.log(formdata);

It works like a charm, even on very complex forms.

share|improve this answer
10  
It is risky to eval user input - anything could happen. I strongly recommend to not do this. – naomik Feb 18 '13 at 21:58

My code from my library phery got a serialization routine that can deal with really complex forms (like in the demo https://github.com/pocesar/phery/blob/master/demo.php#L1664 ), and it's not a one-size-fits-all. It actually checks what the type of each field is. For example, a radio box isn't the same as a range, that isn't the same as keygen, that isn't the same as select multiple. My function covers it all, and you can see it at https://github.com/pocesar/phery/blob/master/phery.js#L1851.

serializeForm:function (opt) {
    opt = $.extend({}, opt);

    if (typeof opt['disabled'] === 'undefined' || opt['disabled'] === null) {
        opt['disabled'] = false;
    }
    if (typeof opt['all'] === 'undefined' || opt['all'] === null) {
        opt['all'] = false;
    }
    if (typeof opt['empty'] === 'undefined' || opt['empty'] === null) {
        opt['empty'] = true;
    }

    var
        $form = $(this),
        result = {},
        formValues =
            $form
                .find('input,textarea,select,keygen')
                .filter(function () {
                    var ret = true;
                    if (!opt['disabled']) {
                        ret = !this.disabled;
                    }
                    return ret && $.trim(this.name);
                })
                .map(function () {
                    var
                        $this = $(this),
                        radios,
                        options,
                        value = null;

                    if ($this.is('[type="radio"]') || $this.is('[type="checkbox"]')) {
                        if ($this.is('[type="radio"]')) {
                            radios = $form.find('[type="radio"][name="' + this.name + '"]');
                            if (radios.filter('[checked]').size()) {
                                value = radios.filter('[checked]').val();
                            }
                        } else if ($this.prop('checked')) {
                            value = $this.is('[value]') ? $this.val() : 1;
                        }
                    } else if ($this.is('select')) {
                        options = $this.find('option').filter(':selected');
                        if ($this.prop('multiple')) {
                            value = options.map(function () {
                                return this.value || this.innerHTML;
                            }).get();
                        } else {
                            value = options.val();
                        }
                    } else {
                        value = $this.val();
                    }

                    return {
                        'name':this.name || null,
                        'value':value
                    };
                }).get();

    if (formValues) {
        var
            i,
            value,
            name,
            $matches,
            len,
            offset,
            j,
            fields;

        for (i = 0; i < formValues.length; i++) {
            name = formValues[i].name;
            value = formValues[i].value;

            if (!opt['all']) {
                if (value === null) {
                    continue;
                }
            } else {
                if (value === null) {
                    value = '';
                }
            }

            if (value === '' && !opt['empty']) {
                continue;
            }

            if (!name) {
                continue;
            }

            $matches = name.split(/\[/);

            len = $matches.length;

            for (j = 1; j < len; j++) {
                $matches[j] = $matches[j].replace(/\]/g, '');
            }

            fields = [];

            for (j = 0; j < len; j++) {
                if ($matches[j] || j < len - 1) {
                    fields.push($matches[j].replace("'", ''));
                }
            }

            if ($matches[len - 1] === '') {
                offset = assign_object(result, fields, [], true, false, false);

                if (value.constructor === Array) {
                    offset[0][offset[1]].concat(value);
                } else {
                    offset[0][offset[1]].push(value);
                }
            } else {
                assign_object(result, fields, value);
            }
        }
    }

    return result;
}

It's part of my library phery, but it can be ported to your own project. It creates arrays where there should be arrays, it gets the correct selected options from the select, normalize checkbox options, etc. If you want to convert it to JSON (a real JSON string), just do JSON.stringify($('form').serializeForm());

share|improve this answer
2  
ok but the the serializeForm is part of my library and does exactly what the OP wants – pocesar Dec 7 '12 at 3:12

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:

<places>

    <place>

        <name>Home</name>
        <type>dwelling</type>

        <activity>sleep</activity>
        <activity>eat</activity>
        <activity>watch TV</activity>

    </place>

    <place>...</place>

    <place>...</place>

</places>

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>
        </select>

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

    </fieldset>

</form>

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-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!

share|improve this answer

This is an improvement for Tobias Cohen's function, which works well with multidimensional arrays:

http://jsfiddle.net/BNnwF/2/

However, this is not a jQuery plugin, but it will only take a few seconds to make it into one if you wish to use it that way: simply replace the function declaration wrapper:

function serializeFormObject(form)
{
    ...
}

with:

$.fn.serializeFormObject = function()
{
    var form = this;
    ...
};

I guess it is similar to macek's solution in that it does the same thing, but i think this is a bit cleaner and simpler. I also included macek's test case inputs into the fiddle and added some additional ones. So far this works well for me.

function serializeFormObject(form)
{
    function trim(str)
    {
        return str.replace(/^\s+|\s+$/g,"");
    }

    var o = {};
    var a = $(form).serializeArray();
    $.each(a, function() {
        var nameParts = this.name.split('[');
        if (nameParts.length == 1) {
            // New value is not an array - so we simply add the new
            // value to the result object
            if (o[this.name] !== undefined) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        }
        else {
            // New value is an array - we need to merge it into the
            // existing result object
            $.each(nameParts, function (index) {
                nameParts[index] = this.replace(/\]$/, '');
            });

            // This $.each merges the new value in, part by part
            var arrItem = this;
            var temp = o;
            $.each(nameParts, function (index) {
                var next;
                var nextNamePart;
                if (index >= nameParts.length - 1)
                    next = arrItem.value || '';
                else {
                    nextNamePart = nameParts[index + 1];
                    if (trim(this) != '' && temp[this] !== undefined)
                        next = temp[this];
                    else {
                        if (trim(nextNamePart) == '')
                            next = [];
                        else
                            next = {};
                    }
                }

                if (trim(this) == '') {
                    temp.push(next);
                } else
                    temp[this] = next;

                temp = next;
            });
        }
    });
    return o;
}
share|improve this answer

Tobias's solution above is the correct one, however, as commenter @macek pointed out, it does not handle inputs of type foo[bar] and split them into sub-objects.

This is a PHP-only feature, but I still find it very useful to be able to generate the same structure in JavaScript.

I simply modified Tobias's code above, so all credit goes to him. This can probably be made cleaner, but I just whipped it up in five minutes and thought it might be useful.

It does not handle multidimensional arrays or numerically indexed arrays at this time. That is, it will only work with names foo[bar] and not foo[].

jQuery.fn.serializeObjectPHP = function()
{
    var o = {};
    var re = /^(.+)\[(.*)\]$/;
    var a = this.serializeArray();
    var n;
    jQuery.each(a, function() {
        var name = this.name;
        if ((n = re.exec(this.name)) && n[2]) {
            if (o[n[1]] === undefined) {
                o[n[1]] = {};
                o[n[1]][n[2]] = this.value || '';
            } else if (o[n[1]][n[2]] === undefined) {
                o[n[1]][n[2]] = this.value || '';
            } else {
                if(!o[n[1]][n[2]].push) {
                    o[n[1]][n[2]] = [ o[n[1]][n[2]] ];
                }
                o[n[1]][n[2]].push(this.value || '');
            }
        } else {
            if (n && !n[2]) {
                name = n[1];
            }
            if (o[name] !== undefined) {
                if (!o[name].push) {
                    o[name] = [o[name]];
                }
                o[name].push(this.value || '');
            } else {
                o[name] = this.value || '';
            }
        }
    });
    return o;
};
share|improve this answer

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, '');

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

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.

share|improve this answer

If you are trying to convert all form fields to JSON in order to submit this form through Ajax here is a jQuery form plugin that does that.

share|improve this answer

I had to shameless self-promote my form library.

transForm.js

It does things like: serialize, deserialize, clear & submit forms.

The reason why I made this is form2js/js2form is not maintained and is not as flexible & fast as I would like. We use it in production because this is form2js/js2form compatible.

share|improve this answer

Convert forms to JSON LIKE A BOSS


UPDATE: The following code is now deprecated. You can find the current version on GitHub.


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
{
  "honey":{
    "badger":"a"
  },
  "wombat":["b"],
  "hello":{
    "panda":["c"]
  },
  "animals":[
    {
      "name":"d",
      "breed":"e"
    }
  ],
  "crazy":[
    null,
    [
      {"wonky":"f"}
    ]
  ],
  "dream":{
    "as":{
      "vividly":{
        "as":{
          "you":{
            "can":"g"
          }
        }
      }
    }
  }
}

Usage

$('#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);
share|improve this answer
10  
So, that works pretty well. But it's misnamed: it doesn't return JSON, as the name implies. Instead, it returns an object literal. Also, it's important to check for hasOwnProperty, otherwise your arrays have anything that's attached to their prototype, like: {numbers: ["1", "3", indexOf: function(){...}]} – frontendbeauty Dec 29 '11 at 0:44
3  
@frontendbeauty actually, toJSON is exactly what the spec says it should be called: developer.mozilla.org/en/JSON#toJSON()_method an unfortunate misnomer. – rpflo May 23 '12 at 17:21
3  
@Marek, I did a test for here on jsfiddle. The trick is to name your select properly. <select name="foo" multiple="multiple"> will not work in any scenario. However, if you use [], as in <select name="bar[]" multiple="multiple">, it will work just fine :) – maček Jan 31 '13 at 18:14
5  
This solution should be on top as it deals with the problem of nested keys as form element names. – SquareCat Feb 23 '14 at 0:34
2  
I agree that this is the more robust solution. If you have more than just a flat set of data you will need this solution. In my case, I have arrays of sub types (e.g. Reservations have an array of Payments). This solutions returned an array of subdocuments called Payments with each payment attribute. Love it! – Michael Moser Mar 6 '14 at 22:42

Use $('#formName').serializeObject()

share|improve this answer

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.

Given:

<form id="myform">
    <label>Name:</label>
    <input type="text" name="name"/>
    <label>Email</label>
    <input type="text" name="email"/>
    <label>Password</label>
    <input type="password" name="password"/>
</form>

Running:

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

Produces:

{"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()));
}
share|improve this answer

What's wrong with:

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 
share|improve this answer
1  
hahahaha :) got more powerfull and more simple code to use, thanks mate – Nova Herdi Kusumah Oct 26 '13 at 4:46
1  
Very simple and effective, but how do you make it account for radio groups where no radio is selected? – LayZee Nov 25 '13 at 7:10
10  
if you're not returning anything, why don't you just use .each instead of .map ?? – Bludream Nov 6 '14 at 10:14
6  
This should be the top answer. – Tool Apr 5 at 14:30
7  
It's so simple because it's super naive... doesn't handle checkboxes with same name. Each time it will override checked item before it. You'll definitely need some input type detection to ensure it's properly serialized. – Joshua Rountree Apr 8 at 14:35

This solution is better. Some of the more popular options on here don't correct handle checkboxes when the checkbox is not checked.

       getData: function(element){
      //@todo may need additional logic for radio buttons
      var select = $(element).find('select');
      var input = $(element).find('input');
      var inputs = $.merge(select,input);
      var data = {};
      //console.log(input,'input');
      $.each(inputs,function(){
        if($(this).attr('type') != undefined){
          switch($(this).attr('type')){
            case 'checkbox':
              data[$(this).attr('name')] = ( ($(this).attr('checked') == 'checked') ? $(this).val():0 );
              break;
            default:
              data[$(this).attr('name')] = $(this).val();
              break;
          }
        }
        else{
          data[$(this).attr('name')] = $(this).val();
        }
      })
      return data;
   }
share|improve this answer

protected by Josh Crozier May 30 '14 at 20:18

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.