0

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>
Mr Biscuit
  • 17
  • 8

1 Answers1

0

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>
Community
  • 1
  • 1
Dhiraj
  • 33,140
  • 10
  • 61
  • 78
  • I have accepted your answer but am now unable to submit the string to the API as values for keys adultCount and solutions need to be integers. How do I access the object and change these two values to remove the quotes? I don't want to strip the whole array, just those two values. New question asked here: http://stackoverflow.com/questions/29571269/access-serialized-object-to-submit-form-values-as-integer-to-api – Mr Biscuit Apr 10 '15 at 21:51
  • your answer is perfect. I was already investigating parseInt but you made its usage clear for me. Thanks. – Mr Biscuit Apr 10 '15 at 23:40
  • I'm glad it helped. If this answers your question, please delete the other question you created :) – Dhiraj Apr 10 '15 at 23:52
  • The issue now is that the returned JSON is in a different structure. The slice array looks different and now has curlys and a zero rather than an array and can't be submitted in the required format: {"request":{"slice":{"0":{"origin":"BOS","destination":"LAX","date":"2015-09-09"}},"passengers":{"adultCount":1},"solutions":1}}. – Mr Biscuit Apr 11 '15 at 00:06
  • I just realized that my solution will not work. Because there is inconsistency in the desired structure of the request. if `slice` is an array of objects then serializeObject would consider passengers as array of objects too. But that is not the required format. So I would suggest to manually prepare the structure instead of doing a `serializeObject` – Dhiraj Apr 11 '15 at 02:32
  • This isn't working for me. The `+item.value` piece is inserting a 0 into a string field that is empty. – Airn5475 Dec 20 '22 at 13:35