42

This question is related with:

Cannot pass null to server using jQuery AJAX. Value received at the server is the string "null"

But I'm asking it again because the solution in that question is very ugly, and I think must be a better one.

PROBLEM
When you send data with jQuery Ajax to PHP using POST you get strings "false"(string) instead of false(bool), "true" instead of true(bool) and "null" instead of NULL:

SOLUTION
(proposed in the above question): convert the data to JSON before send it with jQuery, and then decode that data in PHP. With code:

Javascript code:

$.ajax
(
   {
      url     : <server_url>,
      dataType: 'json',
      type    : 'POST',
      success : receiveAjaxMessage,
      data    : JSON.stringify
      (
         {
            valueTrue : true,
            valueFalse: false,
            valueNull : null
         }
      )
   }
);

PHP code:

var_dump(json_decode(file_get_contents('php://input'), true));

To me that's not a solution, only an ugly hack.

The problem in my situation is that I can't use file_get_contents('php://input') to access the $_POST, even more, I can't use $_POST because I'm using HMVC.

And I know I can fix it checking those "false", "true" and "null" in PHP, or sending 1 and 0 instear true and false in jQuery.
But I think this must be a really common problem, and jQuery is a really common framework, so I'm pretty sure there's a better and elegant way to send the data with the right type in jQuery.

Community
  • 1
  • 1
Enrique
  • 4,693
  • 5
  • 51
  • 71
  • Last I checked, it didn't matter if it is sent as a string or actually true: http://codepad.viper-7.com/otQet7 – Cyclone Sep 13 '11 at 21:51
  • jQuery isn't pure magic, it must obey the html spec, everything is sent as a string, just like POST and GET. Type conversion is a server side issue. – Quaternion Sep 13 '11 at 21:59
  • that's because you are chicking for true, any string that is not empty in PHP is casted to true, check this instead: http://codepad.viper-7.com/aL9P5E – Enrique Sep 13 '11 at 22:00
  • @Quaternion I know it must be sent as string, but jQuery could convert false to "0" instead of "false" – Enrique Sep 13 '11 at 22:02
  • No it can't because jQuery is the library but the string conversion is defined by Java Script. – Quaternion Sep 13 '11 at 22:04
  • why not? maybe it could do something like: if(boolValue === true) boolValue = 1; else if(boolValue === false) boolBalue = 0; or maybe something like if(typeof boolValue === "boolean") boolValue = boolValue ? 1 : 0; – Enrique Sep 13 '11 at 22:16
  • Well you're right, it could but when I look at that code I know I'm sending strings and I know that "valueTrue : true" sets valueTrue to 'true' because of the way JS works and toString will resolve to 'true'. It's a "when in Rome" kind of thing, you have the perspective JS should be serving PHP when JS is used by many languages and in many of them this is a complete non issue. – Quaternion Sep 13 '11 at 22:36
  • Wouldn't it be easier to use 0 & 1? – Ben Sep 13 '11 at 23:03
  • really? in what language(string)"false" is equals to (bool)false? I think in almost any language (string)"0" is converted to (bool)false, so it's not only for PHP, it's a more robust way to send bool parameters why jQuery (and JS at really) converts (bool)false to the string "false" instead to the string "0"??? – Enrique Sep 14 '11 at 11:51
  • Just use -- dataType: 'json' -- in your AJAX request – Sohail xIN3N Aug 15 '14 at 10:48
  • Possible duplicate of [boolean variables posted through AJAX being treated as strings in server side](https://stackoverflow.com/questions/3654454/boolean-variables-posted-through-ajax-being-treated-as-strings-in-server-side) – Adam Jun 29 '19 at 10:12
  • A good answer might be found here: https://stackoverflow.com/a/20463398/2311074 – Adam Jun 29 '19 at 10:13

5 Answers5

52

In my experience if you have

dataType: 'json'

and

contentType: 'application/json'

in your jQuery ajax call, and JSON.stringify your data before you send it will arrive at the server as a parse-able javascript object. Or in my case I'm using NodeJS serverside and it arrives as a Javascript object, with correct booleans, not string bools. But if I leave out the content type attribute then things get all goofed up including the bools.

skinneejoe
  • 3,921
  • 5
  • 30
  • 45
  • Maybe it is worth mentioning that the names of the AJAX parameters for jQuery are chosen in a very unlucky and confusing way. Semantically, the parameters `contentType` and `data` on the one hand side as well as `dataType` and `content` on the other hand side form a logical group. In order to transmit something from the client to the server the payload is put into `data` and the type of data is specified by `contentType`. In the reverse direction, in order to receive something from the server, the payload is put into `content` and the expected type is specified by `dataType`. Yikes! – user2690527 Sep 08 '21 at 14:55
19

Because HTTP is a text protocol with no concept of booleans or integers everything must be stringified. Comparing strings on the server side is the normal way to deal with booleans.

If you really really want PHP to see a 0 or 1 you can use

 valueTrue : true ? 1 : 0

in your AJAX call.

regularmike
  • 1,167
  • 10
  • 22
codelove
  • 1,988
  • 5
  • 26
  • 36
  • This answer is not solid. The JSON string `{myBoolean: true}` is also a literal text and hence can be transported via HTTP. There is no need to add extra hyphens as in `{myBoolean: "true"}`. The former is correct and the server will interpret `myBoolean` as a boolean type, while the latter is wrong and `myBoolean` equals a string value. It is just a bug in the conversion routine of jQuery. The argument "HTTP is a text protcol" is not substantial. – user2690527 Sep 08 '21 at 14:11
5

I ran into the same issue. I solved it by sending a 1 or 0 for booleans.

In the $.ajax I did data : {field_name: field ? 1 : 0}

Ariel
  • 25,995
  • 5
  • 59
  • 69
  • It still parses as a string "1" or "0" on the server side. – Adam Jun 27 '19 at 18:02
  • @Adam That's correct, but PHP will automatically convert "1" and "0" to booleans, but it won't convert "true" and "false". – Ariel Jun 30 '19 at 03:33
0

I tried using Boolean object instead of primitive boolean type in the model at controller and it worked.

I have contentType : 'application/json; charset=utf-8' and data type as "POST".

loakesh bachhu
  • 323
  • 3
  • 4
0

If you will not handle the type conversion on the server then you must send what you expect.

Instead of:

     {
        valueTrue : true,
        valueFalse: false,
        valueNull : null
     }

Use:

     {
        valueTrue : 'TRUE',
        valueFalse: 'FALSE',
        valueNull : 'NULL'
     }

A ternary operator is pretty clear...

 valueTrue: (myvar ? 'TRUE' : 'FALSE')

But probably clearer is to append ".toString().toUpperCase()" to the variables :

 valueTrue : myvar.toString().toUpperCase();

However that will not work if myvar is null...

This example shows a converter function you can use before sending data.

<html>
    <head>
        <script>
            function myConverter(toUpper){
                if (toUpper != null){
                   return toUpper.toString().toUpperCase(); 
                }
                return 'NULL';
            }
            //tests
            alert(myConverter(null));
            alert(myConverter(true));
            alert(myConverter(false));
        </script>
    </head>
    <body>
    </body>
</html>
Mr.Singh
  • 1,421
  • 6
  • 21
  • 46
Quaternion
  • 10,380
  • 6
  • 51
  • 102
  • 1
    maybe the null value is the most difficult to cast, but I think the solution is to convert (bool)false to (string)"0" in JS side (jQuery). In PHP the string "0" is equals to false (but "false" is equals to true). – Enrique Sep 13 '11 at 22:08
  • mmm... reading your reply again I think you misinterpreted my question, when I said that in PHP I'm receiving "false" instead of FALSE I was refering to (string)"false" instead of (bool)FALSE, is not about converting to uppercase the string "false" but converting it to a real bool type (FALSE, false, or even 0 and "0" or "", but not "false", "FALSE", or "AnyString different than empty or 0" in PHP). – Enrique Sep 15 '11 at 00:14
  • Then I have no idea why you showed any JS in your question at all if it isn't part of the solution. All we can sent from the client are strings. I showed how you can wrap booleans and null to send what ever you want. Beyond that you have server side issues. – Quaternion Sep 16 '11 at 06:08
  • I know I can fix this in a million of ways. My english is not so good, but I tried to left in clear that I was looking for an elegant solution because I feel that this is a really common problem (I put a link to the exactly same question, but with an ugly solution). With an elegant solution I mean something native in jQuery, for example some flag that we can set so jQuery converts (bool)false into (string)"0" instead (string)"false". – Enrique Sep 16 '11 at 14:18