1771

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

2
  • 19
    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 Commented Jul 26, 2009 at 14:05
  • The best library to read and set a form data as JSON is FormDataJson. This JSON is not flat as FormData is! The returned data is like at this answer. Though this is not jQuery solution, this is very small standalone library.. Commented Aug 25, 2024 at 2:02

58 Answers 58

1
2
2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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!

1 Comment

what are you trying to do?
2

So I used the accepted answer and found a major flaw.
It doesn't support input arrays like:

<input type="checkbox" name="array[]" value="1"/>
<input type="checkbox" name="array[]" value="2"/>
<input type="checkbox" name="array[]" value="3"/>

This minor change should fix that:

function objectifyForm(inp){
    var rObject = {};
    for (var i = 0; i < inp.length; i++){
        if(inp[i]['name'].substr(inp[i]['name'].length - 2) == "[]"){
            var tmp = inp[i]['name'].substr(0, inp[i]['name'].length-2);
            if(Array.isArray(rObject[tmp])){
                rObject[tmp].push(inp[i]['value']);
            } else{
                rObject[tmp] = [];
                rObject[tmp].push(inp[i]['value']);
            }
        } else{
            rObject[inp[i]['name']] = inp[i]['value'];
        }
    }
    return rObject;
}

Remember to pass it the output from $(this).serializeArray(); otherwise it wont work.

1 Comment

Yes! So many upvoted answers, but only this one works properly with checkboxes. Thanks
1

I wouldn't use this on a live site due to XSS attacks and probably plenty of other issues, but here's a quick example of what you could do:

$("#myform").submit(function(){
    var arr = $(this).serializeArray();
    var json = "";
    jQuery.each(arr, function(){
        jQuery.each(this, function(i, val){
            if (i=="name") {
                json += '"' + val + '":';
            } else if (i=="value") {
                json += '"' + val.replace(/"/g, '\\"') + '",';
            }
        });
    });
    json = "{" + json.substring(0, json.length - 1) + "}";
    // do something with json
    return false;
});

1 Comment

Couldn't you get around XSS attacks by converting them to JS object first, instead of directly to string?
1

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

1 Comment

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

using lodash#set

let serialized = [
  { key: 'data[model][id]', value: 1 },
  { key: 'data[model][name]', value: 'product' },
  { key: 'sid', value: 'dh0un1hr4d' }
];

serialized.reduce(function(res, item) {
  _.set(res, item.key, item.value);
  return res;
}, {});

// returns
{
  "data": {
    "model": {
      "id": 1,
      "name": "product"
    }
  },
  "sid": "dh0un1hr4d"
}

1 Comment

I like this solution, but it doesn't handle form fields in key[] array format; [ {key: 'items[]', value: 1 }, {key: 'items[]', value: 2 } ] results in { items: { "": 2 } }.
1

A more modern way is to use reduce with serializeArray() in this way:

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

It will help for many of the 'normal' cases.

For the very common instance where there are multiple tags with duplicate name attributes, this is not enough.

Since inputs with duplicate name attributes are normally inside some 'wrapper' (div, ul, tr, ...), like in this exemple:

  <div class="wrapperClass">
    <input type="text" name="one">
    <input type="text" name="two">
  </div>
  <div class="wrapperClass">
    <input type="text" name="one">
    <input type="text" name="two">
  </div>

one can use reduce with the map operator to iterate on them:

$(".wrapperClass").map(function () {
  return $(this).find('*').serializeArray()
    .reduce((a, x) => ({ ...a, [x.name]: x.value }), {});
}).get();

The result will be an array of objects in the format:

  [
    {
      one: valueOfOne,
      two: valueOfTwo
    }, {
      one: valueOfOne,
      two: valueOfTwo
    }
  ]

The .get() operator is used in conjunction with map to get the basic array instead of the jQuery object which gives a cleaner result. jQuery docs

Comments

1

Javascript / jQuery one-liner-ish - which works on older versions too (pre ES6):

$('form').serializeArray().reduce((f,c) => {f[c['name']]=(f[c['name']])?[].concat(f[c['name']],c['value']):c['value']; return f}, {} );

Comments

1

This uses the foreach method to iterate over the name and value pair returned by serializeArray and then return an object using the names as key.

  let formData = $(this).serializeArray();
  let formObject = {}
  formData.forEach(
    x=>formObject.hasOwnProperty(x.name)?formObject[x.name]=[formObject[x.name],x.value].flat():formObject[x.name]=x.value
  );

Comments

1

This will work exact same which you want

  • Execute following code only once
$.fn.serializeObject = function(){
    let d={};
    $(this).serializeArray().forEach(r=>d[r.name]=r.value);
    return d;
}
  • Now you can execute following line any number of times
let formObj = $('#myForm').serializeObject();
// will return like {id:"1", username:"abc"}

1 Comment

If the form include same name input fields only return the last one, =/
1

For semantic-ui/fomantic-ui, there is a built-in behavior get values:

const fields = $("#myForm.ui.form").form('get values');
const jsonStr = JSON.stringify(fields);

See https://fomantic-ui.com/behaviors/form.html#/settings

get values(identifiers) Returns object of element values that match array of identifiers. If no IDS are passed will return all fields

Comments

0

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

Comments

0

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

3 Comments

Stack Overflow isn't here for you to promote your library.
ok but the the serializeForm is part of my library and does exactly what the OP wants
The last string is the best
0

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>

Comments

0

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

Comments

0

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

Comments

0

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;

})();

Comments

0

This code working for me :

  var data = $('#myForm input, #myForm select, #myForm textarea').toArray().reduce(function (m, e) {
            m[e.name] = $(e).val();
            return m;
        }, {});

Comments

0

This code convert and save type of inputs and not convert all to string:

jQuery.fn.serializeForm = function () {
    var form = this.get(0);
    var i = [];
    var ret = {};
    for (i = form.elements.length - 1; i >= 0; i = i - 1) {
        if (form.elements[i].name === "") {
            continue;
        }
        var name = form.elements[i].name;
        switch (form.elements[i].nodeName) {
            case 'INPUT':
                switch (form.elements[i].type) {
                    case 'text':
                    case 'tel':
                    case 'email':
                    case 'hidden':
                    case 'password':
                        ret[name] = encodeURIComponent(form.elements[i].value);
                        break;
                    case 'checkbox':
                    case 'radio':
                        ret[name] = form.elements[i].checked;
                        break;
                    case 'number':
                        ret[name] = parseFloat(form.elements[i].value);
                        break;
                }
                break;
            case 'SELECT':
            case 'TEXTAREA':
                ret[name] = encodeURIComponent(form.elements[i].value);
                break;
        }
    }
    return ret;
};

For example this is output:

Day: 13
Key: ""
Month: 5
OnlyPayed: true
SearchMode: "0"
Year: 2021

instead of

Day: "13"
Key: ""
Month: "5"
OnlyPayed: "true"
SearchMode: "0"
Year: "2021"

Comments

0

This handles multiple select or even elements with the same name:

$.fn.formToJSON = function(){
    pairStr=this.serialize();
    let rObj={};
    pairStr.split(`&`).forEach((vp)=> {
        prop=vp.split(`=`)[0];
        val=vp.split(`=`)[1];
        if(rObj.hasOwnProperty(prop)) {
            if (Array.isArray(rObj[prop])) {
                rObj[prop].push(val);
            } else {
                rObj[prop]=[rObj[prop]];
                rObj[prop].push(val);
            }
        } else {
            rObj[prop]=val;
        }
    });
    return JSON.stringify(rObj);
}

Comments

0

This thread seems to have become the collective FAQ for Form serialization :)

My Take on the PHP-Naming: <input name="user[name]" >

$('form').on('submit', function(ev) {
   ev.preventDefault();

   var obj = $(this).serializePHPObject();

   // $.post('./', obj);
});
(function ($) {
  // based on https://stackoverflow.com/a/25239999/1644202

  // <input name="user[name]" >
  $.fn.serializePHPObject = function () {
    var obj = {};
    $.each(this.serializeArray(), function (i, pair) {
      var cObj = obj,
        pObj,
        cpName;
      $.each(pair.name.split("["), function (i, pName) {
        pName = pName.replace("]", "");
        pObj = cObj;
        cpName = pName;
        cObj = cObj[pName] ? cObj[pName] : (cObj[pName] = {});
      });
      pObj[cpName] = pair.value;
    });
    return obj;
  };
})(jQuery);

Comments

0

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

Comments

0

That will take everything into consideration

  function formToObject(form) {
    
    
    let data = new FormData(form);
    let queryString = new URLSearchParams(data).toString();
      var obj = {};
      var params = queryString.split("&");
      for (var i = 0; i < params.length; i++) {
        var param = params[i].split("=");
    
         var key = param[0].replace("[]", "");
         var key = key.replace("%5B%5D", "");
         
        var value = param[1];
        if (obj[key] === undefined) {
          obj[key] = value;
        } else if (obj[key] instanceof Array) {
          obj[key].push(value);
        } else {
          obj[key] = [obj[key], value];
        }
      }
      console.log(obj)
      return obj;
    }
  <!DOCTYPE html>
<html>
  <head>
    <title>Form Example</title>
  </head>
  <body style="height:800px;overflow:scroll">
    <form id="test" onchange="formToObject(this)"><div><h3>fruits</h3>
    <input type="checkbox" name="fruit" value="apple" id="apple">
<label for="apple">Apfel</label>

<input type="checkbox" name="fruit" value="banana" id="banana">
<label for="banana">Banane</label>

<input type="checkbox" name="fruit" value="cherry" id="cherry">
<label for="cherry">Kirsche</label>

<input type="checkbox" name="fruit" value="grape" id="grape">
<label for="grape">Traube</label>

<input type="checkbox" name="fruit" value="pear" id="pear">
<label for="pear">Birne</label></div>
<div><h3> multiple options</h3>
   
      <select multiple name="manyOptions[]">
        <option value="Option 1">Option 1</option>
        <option value="Option 2">Option 2</option>
        <option value="Option 3">Option 3</option>
      </select>
    </div>
    <div><h3> Check on option</h3>
      <input type="radio" name="onceOption" value="Option 1">Option 1<br>
      <input type="radio" name="onceOption" value="Option 2">Option 2<br>
      <input type="radio" name="onceOption" value="Option 3">Option 3<br>
   
   </div></form>
  </body>
</html>

Comments

-1

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

Comments

-1

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

Comments

-1

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

var params = {};
$("#form").find("*[name]").each(function(){
    params[this.getAttribute("name")] = this.value;
});

Comments

-1
function serializedArray2Object(array){
    let obj = {};
    array.forEach(function(item){
        if(obj[item['name']] === undefined){
            obj[item['name']] = item['value'];
        }else if(Array.isArray(obj[item['name']])){
            obj[item['name']] = [...obj[item['name']],item['value']]
        }else{
            obj[item['name']] = [obj[item['name']],item['value']];
        }
    });
    return obj;
}

using

serializedArray2Object($('#form').serializeArray())

I just discovered that function from jQuery and wrote a converter to object so the array becomes an object.

Comments

-8

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.

1 Comment

It is risky to eval user input - anything could happen. I strongly recommend to not do this.
1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.