1

I have the typical problem with big int decoded with json_decode and try using the JSON_BIGINT_AS_STRING option, but it seems that php ignores the parameter.

I tried the php.net example code:

$json = '12345678901234567890';

var_dump(json_decode($json));
var_dump(json_decode($json, false, 512, JSON_BIGINT_AS_STRING));

The output should be:

float(1.2345678901235E+19)
string(20) "12345678901234567890"

But in my server (xampp php 5.4.7) I have:

float(1.2345678901235E+19)
float(1.2345678901235E+19)

Thanks for the help!

EduBusquets
  • 135
  • 9
  • JSON_BIGINT_AS_STRING it is by default used by json_decode(). – anuj arora Dec 11 '12 at 09:46
  • @anujarora no it isn't... "Currently only JSON_BIGINT_AS_STRING is supported (default is to cast large integers as floats)" – Matt Humphrey Dec 11 '12 at 09:48
  • 1
    I think it's happening because '12345678901234567890' isn't in JSON format. $json = '{"key":12345678901234567890}'; < that returns as expected.... object(stdClass)#1 (1) { ["key"]=> float(1.2345678901235E+19) } object(stdClass)#1 (1) { ["key"]=> string(20) "12345678901234567890" } – Matt Humphrey Dec 11 '12 at 09:50
  • http://stackoverflow.com/questions/8759314/how-to-get-around-or-make-php-json-decode-not-alter-my-very-large-integer-values – anuj arora Dec 11 '12 at 09:53
  • @Matt Looks like a bug in `json_decode` someone should report...? Technically `1234567890` *is* valid JSON, else `json_decode` should return `false`. – deceze Dec 11 '12 at 09:54
  • 1
    Are you sure you're using PHP 5.4.7 on the server that gives you a float? Because the **options** parameter in `json_decode` was only added in PHP 5.4.0 and I'm not sure if you're saying you have one server running 5.4.7 or both? Can you please make this clear? – Sherif Dec 11 '12 at 10:07
  • @GoogleGuy Reproducible here: http://3v4l.org/nnAUM – deceze Dec 11 '12 at 10:19
  • @Edu While this does look like a bug, it should be a non-issue. It appears to work if the JSON string contains more complex data structures, and if you just have the string as is, you don't need to decode it to begin with. – deceze Dec 11 '12 at 10:21
  • 1
    @deceze Yes, I just realized the example in the documentation is demonstrating the wrong use of the function option. That's not what that option is for. It's for when you have an object or array with a large integer property that is too big to fit as type `int` in PHP and you want it decoded as a string. Of course decoding a JSON string in PHP is just a string in PHP. It won't cast it to int or anything. I fixed the example in the documentation, by the way. – Sherif Dec 11 '12 at 10:32
  • @Google Good job. But just `'123456'` is technically a JSON number, no? Nothing says a JSON int needs to be wrapped in an object/array, though this is arguably the most common use case. Shouldn't it decode as JSON anyway? – deceze Dec 11 '12 at 10:35
  • @deceze Unfortunately, no. PHP's json_decode expects an `a JSON encoded string` and converts it into a PHP variable. So that doesn't include **all valid JSON**, just that subset of JSON that was encoded as either an object or array or string. That's really the defined behavior of that function. I know it's confusing though there have been a number of bugs related to json_decode/encode functions in the past. – Sherif Dec 11 '12 at 10:39
  • @Google That's terrifically incoherent behavior then. `json_encode(1234567890)` correctly returns `1234567890`, but it doesn't decode the other way around... – deceze Dec 11 '12 at 10:41
  • @deceze Actually `var_dump(json_decode(json_encode(1234567890)));` will work. It will give you `int(1234567890)`. It's just not ** guaranteed** to work in every given situation -- or even work as you expect it to (like in the example here). Of course the function is new so it could be argued that this is a bug and that it should be fixed. – Sherif Dec 11 '12 at 10:44
  • @Google OK, better example: `var_dump(json_decode(json_encode(12345678901234567890), false, 512, JSON_BIGINT_AS_STRING))` - does not decode as JSON the way it should... :) – deceze Dec 11 '12 at 10:48
  • @deceze Obviously this is a totally different situation. json_encode got a float from PHP. Look at the output of json_encode() by itself. You encoded a float, which comes out as a string literal. It comes back as the same string literal. Anyway, I handed the bug over to the JSON expert. Hopefully he'll get it fixed :) – Sherif Dec 11 '12 at 11:08
  • Hey guys, thanks for your interest! My problem is that I have a Facebook id (this one: 100004792300343) and with the json_decode I can't retrieve the original string. – EduBusquets Dec 11 '12 at 16:47
  • @deceze : Without going into details, the issue must be a bug, because my example is from original documentation (http://php.net/manual/es/function.json-decode.php) and the result is diferent from mine – EduBusquets Dec 11 '12 at 16:55

1 Answers1

1

EDIT:

I had to confirm this, but this behavior has been classified as a bug in PHP. Please see the bug report for more details.

The existing behavior causes your string to be cast as int/float (number type) internally by PHP. If you provide a JSON encoded object, array, or string the function does what it describes, but for now this reflects the buggy behavior.

$json = '12345678901234567890';

var_dump(json_decode($json));           /* float(1.2345678901235E+19) */
var_dump(json_decode($json, false, 512, 
         JSON_BIGINT_AS_STRING));       /* float(1.2345678901235E+19) */

As you can see both give us a float, but when we use a valid JSON object, array, or valid JSON as a string we get the expected result.

$jsonStr = '"12345678901234567890"';        // as a string
$jsonArr = '[12345678901234567890]';        // as an array
$jsonObj = '{"num":12345678901234567890}';  // as an object

var_dump(
         json_decode($jsonStr), /* It's JSON_BIGINT_AS_STRING by default in 5.4 */
         json_decode($jsonArr),
         json_decode($jsonArr, false, 512, JSON_BIGINT_AS_STRING),
         json_decode($jsonObj),
         json_decode($jsonObj, false, 512, JSON_BIGINT_AS_STRING)
);

The output looks like the following...

string(20) "12345678901234567890"
array(1) {
  [0]=>
  float(1.2345678901235E+19)
}
array(1) {
  [0]=>
  string(20) "12345678901234567890"
}
object(stdClass)#1 (1) {
  ["num"]=>
  float(1.2345678901235E+19)
}
object(stdClass)#2 (1) {
  ["num"]=>
  string(20) "12345678901234567890"
}

This should be fixed soon, but for now I just wanted to update my answer to reflect this new information.

Sherif
  • 11,786
  • 3
  • 32
  • 57