Search code examples
jqueryjsonformsserializationstringify

Serialize Complex Form Input Object to JSON to Make API Request


I have a form whose input I would like to submit to an API in order to obtain a parseable response. So far I have managed to perform the request with a pre formatted object. However, I am having difficulty getting the format required to make the requests.

The structure of the request needs to look like this:

{ "request": { "slice": [ { "origin": "LAX", "destination": "BOS", "date": "2015-09-09" } ], "passengers": { "adultCount": 1 }, "solutions": 1 } };

I have changed the names of the form in an attempt to create the nested keys but what I get is:

{"request[slice][origin]":"LAX","request[slice][destination]":"BOS","request[slice][date]":"2015-09-09","request[passengers][adultcount]":"1","request[solutions]":"1"}

The form looks like this:

<form id="request" action="" onsubmit="request" method="post">
<input type="text" name="request[slice][origin]" placeholder="From">
<br>
<input type="text" name="request[slice][destination]" placeholder="Destination">
<br>
<input type="text" name="request[slice][date]" placeholder="Outbound Date">
<br>
<input type="text" name="request[passengers][adultcount]" placeholder="Passengers">
<br>
<input type="text" name="request[solutions]" placeholder="Results">
<br>
<p><input type="submit" /></p>
</form>

The script that serialises the object is:

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

$(function request() {
$('form').submit(function() {
    $('#result').text(JSON.stringify($('form').serializeObject()));
    return false;
});
});
</script>

Solution

  • The serializeObject method works only for elements with normal inputs. But in your case the inputs have different type of names and thus serializeObject has to be changed a bit.

    $.fn.serializeObject = function () {
        var o = {};
        var outputCopy = o;
        var a = this.serializeArray();
        var regex = /(\w+)+/g; 
        $.each(a, function (index, item) {
            var keys = item.name.match(regex);
            keys.forEach(function (key, localIndex) {
                if (!outputCopy.hasOwnProperty(key)) {
                    outputCopy[key] = {};
                }
                if(localIndex == keys.length - 1) { 
                    outputCopy[key] = isNaN(item.value) ? item.value : +item.value;
                }
                outputCopy = outputCopy[key];
            });
            outputCopy = o;
        });
        return o;
    });
    

    I used regex to break the string request[slice][destination] into request, slice and destination and thus create an object.

    The deepest object's key will have a value. The condition localIndex == keys.length - 1 is used to figure out the last iteration and thus insert a value.

    Hope this helps.

    Update

    check if the value is a string or a number by isNaN and then covert accordingly. + before a string will convert it to a number if it is a number.

    Here is a good reference

    $.fn.serializeObject = function () {
        var o = {};
        var outputCopy = o;
        var a = this.serializeArray();
        var regex = /(\w+)+/g;
        $.each(a, function (index, item) {
            var keys = item.name.match(regex);
            keys.forEach(function (key, localIndex) {
                if (!outputCopy.hasOwnProperty(key)) {
                    outputCopy[key] = {};
                }
                if(localIndex == keys.length - 1) { 
                    outputCopy[key] = isNaN(item.value) ? item.value : +item.value; 
                }
                outputCopy = outputCopy[key];
            });
            outputCopy = o;
        });
        return o;
    };
    
    
    $(function request() {
        $('form').submit(function (e) {
            e.preventDefault();
            alert(JSON.stringify($(this).serializeObject()));
        });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <form id="request" action="" onsubmit="request" method="post">
        <input type="text" name="request[slice][origin]" placeholder="From">
        <br>
        <input type="text" name="request[slice][destination]" placeholder="Destination">
        <br>
        <input type="text" name="request[slice][date]" placeholder="Outbound Date">
        <br>
        <input type="text" name="request[passengers][adultcount]" placeholder="Passengers">
        <br>
        <input type="text" name="request[solutions]" placeholder="Results">
        <br>
        <p>
        <input type="submit" />
        </p>
    </form>