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

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

46 Answers 46

Width all Given Answer there some problem which is...

If input name as array like name[key], but it will generate like this

 name:{
   key : value
 }

For Example : If i have form like this.

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

Then It will Generate Object like this with all given Answer.

Object {
    name : 'value',
    name1[key1] : 'value1',
    name2[key2] : 'value2',
    name3[key3] : 'value3', 
}

But it have to Generate like below,anyone want to get like this as below.

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

Then Try this below js code.

function getFormData2Object(form){
    var un_array = form.serializeArray();
    var _array = {};
    $.map(un_array, function(n, i){
        if(n.name.indexOf('[') > -1 ){
            var array = n.name.match(/\[(.*?)\]/);
            var key = n.name.replace(array[1],"").replace('[',"").replace(']',"");
            if(!_array[key]){
                _array[key] = {};
            }
            _array[key][array[1]] = n['value'];
        }else{
            _array[n['name']] = n['value'];
        }
    });
    return _array;
}
getFormData2Object($('form'))
share|improve this answer

The serialize function take JSON object as a parameter and return serialize String.

function serialize(object) {
            var _SPECIAL_CHARS = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, _CHARS = {
                '\b' : '\\b',
                '\t' : '\\t',
                '\n' : '\\n',
                '\f' : '\\f',
                '\r' : '\\r',
                '"' : '\\"',
                '\\' : '\\\\'
            }, EMPTY = '', OPEN_O = '{', CLOSE_O = '}', OPEN_A = '[', CLOSE_A = ']', COMMA = ',', COMMA_CR = ",\n", CR = "\n", COLON = ':', space = "", COLON_SP = ': ', stack = [], QUOTE = '"';
            function _char(c) {
                if (!_CHARS[c]) {
                    _CHARS[c] = '\\u' + ('0000' + (+(c.charCodeAt(0))).toString(16))
                        .slice(-4);
                }
                return _CHARS[c];
            }
            function _string(s) {
                return QUOTE + s.replace(_SPECIAL_CHARS, _char) + QUOTE;
                // return str.replace('\"','').replace('\"','');
            }

            function serialize(h, key) {
                var value = h[key], a = [], colon = ":", arr, i, keys, t, k, v;
                arr = value instanceof Array;
                stack.push(value);
                keys = value;
                i = 0;
                t = typeof value;
                switch (t) {
                    case "object" :
                        if(value==null){
                            return null;
                        }
                        break;
                    case "string" :
                        return _string(value);
                    case "number" :
                        return isFinite(value) ? value + EMPTY : NULL;
                    case "boolean" :
                        return value + EMPTY;
                    case "null" :
                        return null;
                    default :
                        return undefined;
                }
                arr = value.length === undefined ? false : true;

                if (arr) { // Array
                    for (i = value.length - 1; i >= 0; --i) {
                        a[i] = serialize(value, i) || NULL;
                    }
                }
                else { // Object
                    i = 0;
                    for (k in keys) {
                        if (keys.hasOwnProperty(k)) {
                            v = serialize(value, k);
                            if (v) {
                                a[i++] = _string(k) + colon + v;
                            }
                        }
                    }
                }

                stack.pop();
                if (space && a.length) {

                    return arr
                        ? "[" + _indent(a.join(COMMA_CR), space) + "\n]"
                        : "{\n" + _indent(a.join(COMMA_CR), space) + "\n}";
                }
                else {
                    return arr ? "[" + a.join(COMMA) + "]" : "{" + a.join(COMMA)
                        + "}";
                }
            }
            return serialize({
                "" : object
            }, "");
        }
share|improve this answer

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

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

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
    
it seems as though you didn't read my entire comment. I devised a solution that handles foo[bar]-type inputs as well as foo[bar][bof][a][b][c][etc]; see my answer in this thread. Also note that foo[bar] "parsing" is not unique to PHP. Rails heavily relies on this convention for passing form attributes to objects. – maček May 22 '12 at 3:32

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

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
    
Stack Overflow isn't here for you to promote your library. – Andrew Barber Dec 7 '12 at 3:03
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 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 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

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

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

Has anyone mentioned this link? pretty cool and as easy as $('#myform').formParams();

share|improve this answer

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

share|improve this answer

This function returns all values converted to the right type;

bool/string/(integer/floats) possible

Tho you kinda need jQuery for this, but since serializeArray is jQuery too, so no big deal imho.

/**
 * serialized a form to a json object
 *
 * @usage: $("#myform").jsonSerialize();
 *
 */

(function($) {
    "use strict";
    $.fn.jsonSerialize = function() {
        var json = {};
        var array = $(this).serializeArray();
        $.each(array, function(key, obj) {
            var value = (obj.value == "") ? false : obj.value;
            if(value) {
                // check if we have a number
                var isNum = /^\d+$/.test(value);
                if(isNum) value = parseFloat(value);
                // check if we have a boolean
                var isBool = /^(false|true)+$/.test(value);
                if(isBool) value = (value!=="false");
            }
            json[obj.name] = value;
        });
        return json;
    }
})(jQuery);
share|improve this answer

Create a map and cycle all fields, saving their values.

var params = {};
$("#form").find("*[name]").each(function(){
    params[this.getAttribute("name")] = this.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
11  
It is risky to eval user input - anything could happen. I strongly recommend to not do this. – naomik Feb 18 '13 at 21:58

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

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

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.