47
votes

Is there any better solution to convert a form data that is already serialized by jQuery function serialize(), when the form contains multiple input Array fields. I want to be able to convert the form data in to a JSON object to recreate some other informative tables. So tell me a better way to get the serialize string converted as a JSON object.

<form id='sampleform'>
    <input name='MyName' type='text' /> // Raf

    <!--array input fields below-->
    <input name='friendname[]' type='text' /> // Bily
    <input name='fiendemail[]' type='text' /> // [email protected]

    <!--duplicated fields below to add more friends -->
    <input name='friendname[]' type='text' /> // Andy
    <input name='fiendemail[]' type='text' /> // [email protected]

    <input name='friendname[]' type='text' /> // Adam
    <input name='fiendemail[]' type='text' /> // [email protected]
</form>

The jquery method applied to get the data

var MyForm = $("#sampleform").serialize();
/** result : MyName=Raf&friendname[]=Billy&fiendemail[][email protected]&friendname[]=Andy&fiendemail[][email protected]&friendname[]=Adam&fiendemail[][email protected]
*/

how do I make this data in to a JSON object? which should have the following example JSON data from the above form.

{
    "MyName":"raf",
    "friendname":[
        {"0":"Bily"},
        {"1":"Andy"},
        {"2":"Adam"}
    ],
    "friendemail":[
        {"0":"[email protected]"},
        {"1":"[email protected]"},
        {"2":"[email protected]"}
    ]
}
13
Technically, that's not how the JSON object would be formatted based on your query string. Specifically, the array elements would not be objects with indexes, but just values. With that said, if you require the format you posted, you will probably need to write a custom function.Jason McCreary
You can use this plugin.SLaks
possible duplicate of Serialize form to JSON with jQuerySLaks
Thanks Slaks and Jason, yes I do agree that I need a function to do it and Slaks have pointed it out for me.Raftalks
2018 people, several years after this question being answered, I tried multiple solutions from here and RECOMEND tothemario solution: github.com/marioizquierdo/jquery.serializeJSON It really works even when you use 'object[attribute]' form to name your inputs.Dimas Crocco

13 Answers

59
votes
var formdata = $("#myform").serializeArray();
var data = {};
$(formdata ).each(function(index, obj){
    data[obj.name] = obj.value;
});

Simple and fast ;)

13
votes

I have recently had this exact problem. 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.

8
votes

Use the jQuery.serializeJSON plugin. It converts forms using the same format as what you would find in a Rails params object, which is very standard and well tested.

6
votes

I'm using this very little jQuery plugin, that I've extended from DocumentCloud:

https://github.com/documentcloud/documentcloud/blob/master/public/javascripts/lib/jquery_extensions.js

It is basically two lines of code, but it requires _.js (Underscore.js), since it is based on a reduce function.

$.fn.extend({
  serializeJSON: function(exclude) {
    exclude || (exclude = []);
    return _.reduce(this.serializeArray(), function(hash, pair) {
      pair.value && !(pair.name in exclude) && (hash[pair.name] = pair.value);
      return hash;
    }, {});
  }
});

Extensions:

  • It doesn't serialize an input value if it's null
  • It can exclude some inputs by passing an array of input names to the exclude argument i.e. ["password_confirm"]
5
votes

I think there're a lot of good answer here, and I made my own function based on these answers.

function formToJSON(f) {
    var fd = $(f).serializeArray();
    var d = {};
    $(fd).each(function() {
        if (d[this.name] !== undefined){
            if (!Array.isArray(d[this.name])) {
                d[this.name] = [d[this.name]];
            }
            d[this.name].push(this.value);
        }else{
            d[this.name] = this.value;
        }
    });
    return d;
}

//The way to use it :
$('#myForm').submit(function(){
    var datas = formToJSON(this);
    return false;
});

Well let me explain basically why I prefer this solution... If you have multiples input with the same name, all values will be stored in an Array but if not, the value will be stored directly as the value of the index in the JSON ... This is where it's different from Danilo Colasso's answer where the JSON returned is only based of array values...

So if you have a Form with a textarea named content and multiples authors, this function will return to you :

{
    content : 'This is The Content',
    authors : 
        [
            0: 'me',
            1: 'you',
            2: 'him',
        ]
}
4
votes

An equivalent solution to Danilo Colasso's, with the sames pros and cons of .serializeArray() (basically it uses .reduce instead of $.each).

With little effort it allows implementing the extra features in S.C.'s answers without requiring extensions.

$(selector).serializeArray()
    .reduce(function(accum, item) {
        // This 'if' allows ignoring some values
        if (-1 === [ 'ignoreThis', 'andThat' ].indexOf(item.name)) {
            // This allows ignoring NULL values
            if (item.value !== null) {
                accum[item.name] = item.value;
            }
        }
        return accum;
    },
    {
        // By supplying some initial values, we can add defaults
        // for, say, disabled form controls.
        preFilledName:  preFilledValue, // optional
        defaultName  :  defaultValue    // optional
    }
);
3
votes
var formdata = $("#myform").serializeArray();

var data = {};

$(formdata ).each(function(index, obj){

         if(data[obj.name] === undefined)
              data[obj.name] = [];

          data[obj.name].push(obj.value);

});
3
votes

if you can use ES6, you could do

const obj = arr.reduce((acc, {name, value}) => ({...acc, [name]: value}), {})

for a serialized array works very well.

2
votes

Using underscore & jQuery

var formdata = $("#myform").serializeArray();
var data = {};
_.each(formdata, function(element){
// Return all of the values of the object's properties.
  var value = _.values(element);
// name : value 
  data[value[0]] = value[1];
});
console.log(data); //Example => {name:"alex",lastname:"amador"}
1
votes

Using the power of reducing function!

$(form).serializeArray().reduce(function (output, value) {
        output[value.name] = value.value

        return output
}, {})
1
votes

With 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($) {
  $.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());
  });
})(jQuery);
console.log($('form').getForm2obj());
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<form>
  <input name="name" value="value">
  <input name="name1[key1]" value="value1">
  <input name="name2[key2]" value="value2">
  <input name="name3[key3]" value="value3">
  <input type="checkbox" name="name4[]" value="1" checked="checked">
  <input type="checkbox" name="name4[]" value="2">
  <input type="checkbox" name="name4[]" value="3">
</form>
0
votes

if you are using ajax requests then no need to make it json-object only $('#sampleform').serialize() works excellently or if you have another purpose here is my solution:

var formserializeArray = $("#sampleform").serializeArray();   
var jsonObj = {};
jQuery.map(formserializeArray , function (n, i) {
    jsonObj[n.name] = n.value;
});
0
votes

Use JSON.stringify() and serializeArray():

console.log(JSON.stringify($('#sampleform').serializeArray()));