Convert form data to JavaScript object with jQuery

Asked 2023-09-21 08:12:06 View 756,561

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

  • 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 - anyone

Answers

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.

Answered   2023-09-21 08:12:06

  • 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. - anyone
  • 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. - anyone
  • multiple name only return last one. - anyone

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

Answered   2023-09-21 08:12:06

  • 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(){...}]} - anyone

What's wrong with:

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

Answered   2023-09-21 08:12:06

  • $(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {}) - anyone
  • $(this).serializeArray().reduce((o,kv) => ({...o, [kv.name]: kv.value}), {}) - anyone
  • this is the one row solution, though others work too. - anyone
  • You mean other than the fact that this doesn't support form arrays? - anyone

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 {
      value = '';
    }

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

      objectData[this.name].push(value);
    } else {
      objectData[this.name] = value;
    }
  });

  return objectData;
};

And a CoffeeScript version for your coding convenience:

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

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

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

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

  return objectData

Answered   2023-09-21 08:12:06

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).

Answered   2023-09-21 08:12:06

[UPDATE 2020]

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

Object.fromEntries(new FormData(form))

Answered   2023-09-21 08:12:06

  • doesn't handle nested form notation into json. - anyone
  • Obviously as it is not considered as valid html html.spec.whatwg.org/multipage/forms.html#the-form-element, even chromium remove nested form - anyone
  • Perfect answer. - anyone
  • Thank you So Much😍, work for flat Model - anyone
  • I spent a fair bit of time trying to make this work, and in case it helps others; make sure your inputs have names as well as ids, and name your form. Here is the entire line to return JSON ready to send via AJAX: const my_form_data = JSON.stringify( Object.fromEntries( new FormData( document.forms.namedItem( "my-form-name" ) ) ) ); - anyone

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

Answered   2023-09-21 08:12:06

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

Answered   2023-09-21 08:12:06

  • This function returns an object not a JSON string. - anyone

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:

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

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 = n.name.match(/[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 _;
}
console.log($('form').getForm2obj());
$('form input').change(function() {
  console.clear();
  console.log($('form').getForm2obj());
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<form>
  <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">
</form>

Answered   2023-09-21 08:12:06

  • This answer does cover the case mentioned, but it does not cover cases like checkbox[] or even one[another][another_one] - anyone
  • @LeonardoBeal i fix my ans .. check this now ..! - anyone
  • I can't agree this is a good answer. And please when you write answers make your code self-explanatory or explain it. this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);} is short und not explanatory. A dev with less experience will just copy this without understanding why and how it works. - anyone
  • @JackGiffin Check out my new code now because I've removed eval() from my code. - anyone
  • @BhavikHirani After a long search, I found your answer, you saved me a long hours of search! thanks man!! - anyone

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

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

Answered   2023-09-21 08:12:06

  • I am not certain how it worked previously, but now it does not. Changed a bit that works: Object.fromEntries(_.map($('#myform').serializeArray(), _.values)) - anyone

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.name] = $(n).val();
    return o;
});
console.log(obj);

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: n.name, Value: $(n).val() };
});
console.log(obj);

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.

Answered   2023-09-21 08:12:06

  • I tried this in a project, using map like this creates an array of objects with a single property, it does not collapse the properties all into one object. - anyone

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 = {};
  jQuery.map(jQuery(this).serializeArray(), function(n, i) {
    var _ = n.name.indexOf('[');
    if (_ > -1) {
      var o = json;
      _name = n.name.replace(/\]/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]]];
            }
            o[_name[i]].push(n.value);
          }
          else o[_name[i]] = n.value || '';
        }
        else o = o[_name[i]] = o[_name[i]] || {};
      }
    }
    else {
      if (json[n.name] !== undefined) {
        if (!json[n.name].push) {
          json[n.name] = [json[n.name]];
        }
        json[n.name].push(n.value || '');
      }
      else json[n.name] = n.value || '';      
    }
  });
  return json;
};

Answered   2023-09-21 08:12:06

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

$('form').serializeArray().map(function(x){this[x.name] = 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)

Answered   2023-09-21 08:12:06

You can do this:

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

See JSON.

Answered   2023-09-21 08:12:06

  • The question is how to get an object not a JSON string. - anyone

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

Answered   2023-09-21 08:12:06

From some older answer:

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

Answered   2023-09-21 08:12:06

  • From what I can tell, the difference is that your solution does not depend on serializeArray so you have the freedom to choose whatever inputs you want (eg. you can include disabled inputs), right? I.e. this is not coupled to any form or the submit event, it's just independent by itself? - anyone
  • the only small difference with linked answer is that there is no data needed to instantiate, reduce returns the object. This is not independent since toArray is from jQuery. - anyone

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[this.name] == ''" to the first if condition:

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

Answered   2023-09-21 08:12:06

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

Answered   2023-09-21 08:12:06

const formData = new FormData(form);

let formDataJSON = {};

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

    formDataJSON[key] = value;
}

Answered   2023-09-21 08:12:06

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

Answered   2023-09-21 08:12:06

  • This looks like a reply to an answer, not a self contained answer to the question. - anyone

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

Answered   2023-09-21 08:12:06

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.

Answered   2023-09-21 08:12:06

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];
    
    console.log(json)
    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>
</form>

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

FormData: https://developer.mozilla.org/en-US/docs/Web/API/FormData

Answered   2023-09-21 08:12:06

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

            o[name].push(value);
        }

        else {
            o[name] = value;
        }
    });

    return o;
}

Use like so:

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

Only tested in Firefox.

Answered   2023-09-21 08:12:06

Taking advantage of ES6 goodness in a one liner:

$("form").serializeArray().reduce((o, {name: n, value: v}) => Object.assign(o, { [n]: v }), {});

Answered   2023-09-21 08:12:06

Serialize Deep Nested Forms Without JQuery

After spending a couple of days looking for a solution to this problem that has no dependencies, I decided to make a non-jQuery form data serializer, using the FormData API.

The logic in the serializer is largely based on the de-param function from a jQuery plugin called jQuery BBQ, however, all dependencies have been removed in this project.

This project can be found on NPM and Github:

https://github.com/GistApps/deep-serialize-form

https://www.npmjs.com/package/deep-serialize-form

function deepSerializeForm(form) {

  var obj = {};

  var formData = new FormData(form);

  var coerce_types = { 'true': !0, 'false': !1, 'null': null };

  /**
   * Get the input value from the formData by key
   * @return {mixed}
   */
  var getValue = function(formData, key) {

    var val = formData.get(key);

    val = val && !isNaN(val)              ? +val              // number
        : val === 'undefined'             ? undefined         // undefined
        : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
        : val;                                                // string

    return val;
  }

  for (var key of formData.keys()) {

    var val  = getValue(formData, key);
    var cur  = obj;
    var i    = 0;
    var keys = key.split('][');
    var keys_last = keys.length - 1;


    if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {

      keys[keys_last] = keys[keys_last].replace(/\]$/, '');

      keys = keys.shift().split('[').concat(keys);

      keys_last = keys.length - 1;

    } else {

      keys_last = 0;
    }


    if ( keys_last ) {

      for (; i <= keys_last; i++) {
        key = keys[i] === '' ? cur.length : keys[i];
        cur = cur[key] = i < keys_last
        ? cur[key] || (keys[i+1] && isNaN(keys[i+1]) ? {} : [])
        : val;
      }

    } else {

      if (Array.isArray(obj[key])) {

        obj[key].push( val );

      } else if (obj[key] !== undefined) {

        obj[key] = [obj[key], val];

      } else {

        obj[key] = val;

      }

    }

  }

  return obj;

}

window.deepSerializeForm = deepSerializeForm;

Answered   2023-09-21 08:12:06

  • Uncaught TypeError: FormData constructor: Argument 1 does not implement interface HTMLFormElement. I don't understand - anyone

Here's a one-liner using reduce. Reduce is a functional function that takes the return value of the passed function and passes it back to the passed function in the next iteration, along with the nth value from the list.

$('#formid').serializeArray().reduce((o,p) => ({...o, [p.name]: p.value}), {})

We have to use a few of tricks to get this to work:

  • ...o (spread syntax) inserts all the key: value pairs from o
  • Wrap the object we are returning in () to distinguish it from the {} that denote a function
  • Wrap the key (p.name) in []

Answered   2023-09-21 08:12:06

  • I get wrong result if I don't add a init-object to that function: $('form').serializeArray().reduce((o, p) => ({...o, [p.name]: p.value}), {}) - anyone
  • This has been fixed by Pluto. Thank you! - anyone

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

{"coreSKU":"PCGUYJS","name_de":"whatever",...

NOT as

[{"coreSKU":"PCGUYJS"},{"name_de":"whatever"},...

so the function IMO should read:

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

Answered   2023-09-21 08:12:06

  • Thank you.. this makes (as you mentioned) tiny but very important difference. - anyone

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]);
        else
            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 = {};

    $(node).find(params.selector+"["+params.key+"]").each(function()
    {
        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]+'"';
            }
            else
                return ':{"'+escape(arguments[1])+'"';
        })+':"'+value.replace(/[\\"]/gi, function()
        {
            return "\\"+arguments[0]; 
        })+'"'+string.repeat('}', string.count(name, ']'))+"}");

        o = array.merge(o, obj);
    });

    return o;
}
</script>

The output of test:

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

on

<form>
    <input name='input[a]' type='text' value='text'/>
    <select name='input[b]'>
        <option>select</option>
    </select>

    <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'/>
</form>

will yield:

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

Answered   2023-09-21 08:12:07

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":"joe@example.com","password":"mypass"}

If you want to do a jQuery POST with this JSON object:

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}

Answered   2023-09-21 08:12:07