5

I my AJAX POST request is sending my numeric data to my server as string for some reason... Here are my data and the AJAX request:

var data = {
        projectId: $("#projectId").val(),
        startDate: $("#startDate").val(),
        endDate: $("#endDate").val(),
        num_auto_tests: Number($("#num_auto_tests").val()),
        num_manual_tests: Number($("#num_manual_tests").val()),
        num_passed_tests: Number($("#num_passed_tests").val()),
        num_failed_tests: Number($("#num_failed_tests").val()),
        num_unran_tests: Number($("#num_unran_tests").val()),
        test: 3
    };

AJAX query:

$.ajax({
        type: "POST",
        dataType: "json",
        url: "/addreport/+ data.projectId",
        data: data,
        success: function() {
            console.log('success');
        }
    });

console.log(typeof(data.num_auto_tests)); //returns `number`

The server side returns:

{ projectId: 'FDIC-88445',
  startDate: '',
  endDate: '',
  num_auto_tests: '3',
  num_manual_tests: '3',
  num_passed_tests: '3',
  num_failed_tests: '3',
  num_unran_tests: '3',
  test: '3' } 

As you can see, the values that should be numeric are all strings on the server side...

Does anyone know what's going on?

Thanks in advance!

Trung Tran
  • 13,141
  • 42
  • 113
  • 200

5 Answers5

6

I used JSON.stringify to solve this. PFB my ajax call:

var settings = {
  "url": "http://localhost:12345/docker/scale",
  "type": "POST",
  "headers": {
    "Content-Type": "application/json"
  },
  "data": JSON.stringify({ "scale": { "desired-instances": 123 } })
}

$.ajax(settings).done(function (response) {
  console.log(response);
});

By doing this value was passed as an integer only thus no change required in the server-side code.

vaibhavatul47
  • 2,766
  • 4
  • 29
  • 42
4

Your server receives the post in HTTP protocol, it is no wonder your server-side receives a string, as the operation you are executing is not type-secure. This is actually the expected behavior and if you want the elements to become numeric, then convert the parameters to numbers, the exact methodology depends on the server-side language/framework you are using.

EDIT: You can do two things to solve your issue:

  1. You can create a numeric handler/converter, like this:

    function detectNumeric(obj) { for (var index in obj) { if (!isNaN(obj[index])) { obj[index] = Number(obj[index]); } else if (typeof obj === "object") { detectNumeric(obj[index]); } } }

and call this function for any object you want to handle in such a way, or

  1. Pass the parameters as JSON and decode on server.

var my_object = {

  position: 1,
  id: "500",
  text: "hello world",
  greeting: "100, good day to you",
  book: "nineteen eighty four"

};


// iterates over an object's properties 
// and converts numbers as strings to numbers
function detectNumeric(obj) {
  for (var index in obj) {
    // if object property value *is* a number, like 1 or "500"
    if (!isNaN(obj[index])) {
      // convert it to 1 or 500
      obj[index] = Number(obj[index]);
    }
    // to do: explain what this does
    // else if (typeof obj === "object") {
    //  detectNumeric(obj[index]);
    // }
  }

  console.log(my_object)
}

// call function
detectNumeric(my_object);
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • I'm using node/express on the server. – Trung Tran Dec 29 '15 at 00:56
  • @user1547174, then you can combine isNaN with Number to achieve the desired result. – Lajos Arpad Dec 29 '15 at 01:19
  • I added a demo snippet above based on your answer, can you please tell me: 1) why is `!isNaN("")` true? 2) what does the `else if()` block achieve - i commented it out because it was making the function run multiple times and i wasn't sure what its purpose was. Thank You. – user1063287 Sep 09 '18 at 04:33
  • For those looking for handling the similar scenario of string versions of booleans, see this answer: https://stackoverflow.com/a/48929869 – user1063287 Sep 09 '18 at 05:10
2

I believe the default content type for a POST request is to url-encode it. This essentially turns everything into a string value, and are retrieved as such. Depending on what server side architecture you are using, different content types can be used (or subsequently supported manually), for example using content type application/json which can preserve your object structure and types.

Lochemage
  • 3,974
  • 11
  • 11
0

This is my decoder, it can handle multi-dimensional arrays/objects

//running the object through tests
function tryParsingType(unknownObj) {
    if (unknownObj.constructor.name === "String" && !isNaN(parseFloat(unknownObj)))
        return parseFloat(unknownObj);
    else if (unknownObj.constructor.name === "String" && (unknownObj === "true" || unknownObj === "false"))
        return unknownObj === "true";
    else if (unknownObj.constructor.name === "Array" || unknownObj.constructor.name === "Object")
        tryParsingTypes(unknownObj);
    return unknownObj;
}

//works for generic objects and arrays
function tryParsingTypes(genericObj) {
    var type = genericObj.constructor.name;
    if (!(type === "Array" || type === "Object"))
        return;
    var keys = Object.keys(genericObj);
    for (var i = 0; i < keys.length; i++) {
        var object = genericObj[keys[i]];
        genericObj[keys[i]] = tryParsingType(object);
    }
}

//example code below
var testObj = {
    "key5": "-1",
    "key6": "-132.3123",
    "key7": "3421",
    "key10": "true",
    "key11": "false",
    "key12": 'true',
    "key13": 'false',
    "key14": {
        "key1": {
            "key1": "true",
            "key2": {
                "key1337": "-432.2342",
                "key321": {
                    "key1": "-1231.2",
                    "key2": "false"
                }
            }
        },
        "key2": ["true", "false"],
        "key3": 2.5,
        "key4": "3",
        "key5": "40",
        "key6": "40.99441"
    },
    "key15": [1, 2, 2.5, "3", "40", "40.99441"]
};
var testArr = [1, 2, 3, 4, 5, "6", "7", "8", "9", "10", true, false, "true", "false", {
        "key1": 1,
        "key2": 2,
        "key3": 2.5,
        "key4": "3",
        "key5": "40",
        "key6": "40.99441"
    }, [1, 2, 2.5, "3", "40", "40.99441", ["1", "2"]]];

tryParsingTypes(testObj);
tryParsingTypes(testArr);

console.log({
    "testObj": testObj,
    "testArr": testArr
});
0

In my case, I had to change contentType to application/json rather than json because of how the server was processing the data.

hutch90
  • 341
  • 3
  • 15