Bug #66707 [Com]: big int conversion on json_encode/json_decode
| From: | dev at skynar dot co | Date: | Fri, 28 Aug 2015 03:47:16 +0000 |
| Subject: | Bug #66707 [Com]: big int conversion on json_encode/json_decode | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-195580@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=66707&edit=1
ID: 66707
Comment by: dev at skynar dot co
Reported by: sergey dot shilko at gmail dot com
Summary: big int conversion on json_encode/json_decode
Status: Not a bug
Type: Bug
Package: JSON related
Operating System: Linux
PHP Version: 5.5.7
Block user comment: N
Private report: N
New Comment:
A JSON numeric size is not limited by the specification and should not to be related to PHP_INT_MAX,
just put numeric strings into json without quotes, if JSON_NUMERIC_CHECK flag exists.
i'm sending data to another server, and it needs numeric parameters to be numeric. Am i the
only developer in the world who care about variable types?
function bigint_json_fix(&$array, $depth=512){
foreach($array as $key=>$value){
if(is_string($value) && is_numeric($value) && $value <= PHP_INT_MAX){
if((int)$value == $value){
$array[$key]=(int)$value;
}elseif((float)$value == $value){
$array[$key]=(float)$value;
}
}elseif(is_array($value) && $depth > 0){
bigint_json_fix($value, $depth-1);
$array[$key]=$value;
}
}
}
function bigint_json_encode($array, $options=0, $depth=512){
if(($options & JSON_NUMERIC_CHECK) == 0)
return json_encode($array, $options, $depth);
bigint_json_fix($array, $depth);
$json = json_encode($array, $options - JSON_NUMERIC_CHECK, $depth);
return preg_replace('!\:\"([0-9]*)\"([\}\,])!', ':$1$2', $json);
}
echo bigint_json_encode(['myint'=>'43274923749237498273443579'],
JSON_NUMERIC_CHECK); // {"myint":43274923749237498273443579}
okay now i wonna get numeric string out of json:
$data = json_decode('{"myint":43274923749237498273443579}', true, 512,
JSON_BIGINT_AS_STRING)); //PHP Notice: json_decode(): integer overflow detected
echo $data['myint']; // 9223372036854775807 as i expected, result is corrupted.
function bigint_json_decode($json, $assoc=false, $depth=512, $useless_option=0){
if(($useless_option & JSON_BIGINT_AS_STRING) != 0){
$json = preg_replace('!\:([0-9]*)([\}\,])!', ':"$1"$2', $json);
}
$data = json_decode($json, $assoc, $depth, $useless_option);
bigint_json_fix($data);
return $data;
}
$data = bigint_json_decode('{"myint":43274923749237498273443579}');
echo $data['myint']; //43274923749237498273443579
why not to do the same without regular expressions?
Previous Comments:
------------------------------------------------------------------------
[2014-02-13 11:38:00] sergey dot shilko at gmail dot com
okay then, so its expected.
Already using strict datatypes to threat large numbers as strings.
Thanks.
------------------------------------------------------------------------
[2014-02-13 11:35:06] sergey dot shilko at gmail dot com
echo json_last_error();
//0
echo json_last_error_msg();
//No error
------------------------------------------------------------------------
[2014-02-13 11:33:59] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to
report
a bug at http://bugs.php.net/how-to-report.php
Your integer is larger than the 64bit signed range allows. PHP can not represent this as an int, and
just as a float.
------------------------------------------------------------------------
[2014-02-13 11:19:30] sergey dot shilko at gmail dot com
Trying to use:
$encoded = json_encode($facebookIds, JSON_NUMERIC_CHECK);
makes things even worse:
samearray(2) {
[0]=>
float(4.8572380745623E+19)
[1]=>
string(20) "48572380745623087456"
}
array(2) {
[0]=>
float(4.8572380745623E+19)
[1]=>
float(4.8572380745623E+19)
}
It converts "big int" to float, but this is at least visible in var dump.
------------------------------------------------------------------------
[2014-02-13 11:12:17] sergey dot shilko at gmail dot com
#$decoded = json_decode($encoded, false, 512, JSON_BIGINT_AS_STRING);
Makes no difference.
Test script output:
array(2) {
[0]=>
float(4.8572380745623E+19)
[1]=>
string(20) "48572380745623087456"
}
array(2) {
[0]=>
float(4.8572380745623E+19)
[1]=>
string(20) "48572380745623087456"
}
Broken
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=66707
--
Edit this bug report at https://bugs.php.net/bug.php?id=66707&edit=1