Categories
javascript jquery json serialization

Convert form data to JavaScript object with jQuery

1730

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

1

  • 18

    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, 2009 at 14:05

1721

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.

2

  • 71

    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.

    Jul 28, 2009 at 3:05

  • 61

    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.

    Jul 18, 2010 at 23:54


468

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

1

  • 18

    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(){…}]}

    Dec 29, 2011 at 0:44


307

What’s wrong with:

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

4

  • 55

    $(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {})

    – sites

    Jun 13, 2015 at 21:19

  • 4

    $(this).serializeArray().reduce((o,kv) => ({...o, [kv.name]: kv.value}), {})

    Aug 4, 2021 at 12:48

  • this is the one row solution, though others work too.

    – alex

    Nov 25, 2021 at 17:05

  • You mean other than the fact that this doesn’t support form arrays?

    – Adam F

    May 18 at 17:03