php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79958 json_encode does not support JSON_BIGINT_AS_STRING
Submitted: 2020-08-12 00:31 UTC Modified: 2020-08-15 04:14 UTC
From: jmuraca at gmail dot com Assigned:
Status: Not a bug Package: JSON related
PHP Version: Irrelevant OS: windows (all?)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jmuraca at gmail dot com
New email:
PHP Version: OS:

 

 [2020-08-12 00:31 UTC] jmuraca at gmail dot com
Description:
------------
json_encode should be able to accept the parameter JSON_BIGINT_AS_STRING to display large numbers as string and/or numeric rather than scientific notation

my use case is a long number like that is used for some account management identifiers (my included example is fake) and I want to json output the whole number - not a scientific number

Test script:
---------------
// correct, displays scientific notation
$data = array("val" => 1008901020901566350119);
var_dump(json_encode($data));

// correct, displays val as string
$data = array("val" => "1008901020901566350119");
var_dump(json_encode($data)); 

// correct, displays val as numeric
$data = array("val" => "1008901020901566350119");
var_dump(json_encode($data, JSON_NUMERIC_CHECK));

// ERROR, displays val as scientific
// ideally with JSON_BIGINT_AS_STRING val display as numeric and full number
$data = array("val" => "1008901020901566350119");
var_dump(json_encode($data, JSON_NUMERIC_CHECK|JSON_BIGINT_AS_STRING));   

// ERROR, displays val as scientific
// ideally with JSON_BIGINT_AS_STRING val display as numeric and full number
$data = array("val" => 1008901020901566350119);
var_dump(json_encode($data, JSON_BIGINT_AS_STRING));

Expected result:
----------------
$data = array("val" => "1008901020901566350119");
var_dump(json_encode($data, JSON_NUMERIC_CHECK|JSON_BIGINT_AS_STRING));   
// actual: 1.0089010209015663e+21
// expected: 1008901020901566350119



$data = array("val" => 1008901020901566350119);
var_dump(json_encode($data, JSON_BIGINT_AS_STRING));
// actual: 1.0089010209015663e+21
// expected: 1008901020901566350119


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-08-12 06:53 UTC] sjon@php.net
-Status: Open +Status: Not a bug
 [2020-08-12 06:53 UTC] sjon@php.net
it seems you are missing some context in your report - the numbers you use for your examples exceed the 64 bit maximum in PHP (see PHP_INT_MAX).

Given that PHP cannot process or print integers that big, it switches to scientific notation which is better then nothing.

You might have an interesting feature-request when encoding for a 32 bit system
 [2020-08-12 07:21 UTC] cmb@php.net
-Package: *General Issues +Package: JSON related
 [2020-08-12 07:21 UTC] cmb@php.net
json_encode() doesn't support the JSON_BIGINT_AS_STRING option;
this is for json_decode() only.  You'll want to drop the
JSON_NUMERIC_CHECK option as well: <https://3v4l.org/bGaka>.
 [2020-08-12 16:22 UTC] jmuraca at gmail dot com
If I load a long number from a database, which in this case happens to be a valid ID number, I'd like to preserve that formatting and not convert to scientific notation when encoding to JSON. 

I understand the MAX INT value for a system so I can get around this by treating it as a string, but when I call json_encode with the JSON_NUMERIC_CHECK flag set, it converts to scientific notation.

$data = array("val_num" => 1008901020901566350119, "val_string" => "1008901020901566350119", "int" => "1", "string" => "12345");
var_dump(json_encode($data, JSON_NUMERIC_CHECK));
// returns: {"val_num":1.0089010209015663e+21,"val_string":1.0089010209015663e+21,"int":1,"string":12345}


I'd like to be able to handle small int as numbers, and big int as string or numbers.

JSON_BIGINT_AS_STRING feel like the correct parameter to output this - literally any big integers are encoded to a string.
 [2020-08-13 00:13 UTC] a at b dot c dot de
If you load a big integer (one that exceeds PHP_INT_MAX) from a database and you try to use it in PHP as a number, then the conversion to double happens when you store it in PHP.

In your example

$data = array("val_num" => 1008901020901566350119, "val_string" => "1008901020901566350119", "int" => "1", "string" => "12345");

$data['val_num'] is already a floating-point number (try var_dump($data) to see); the conversion has nothing to do with JSON, and the encoder is only given a floating-point PHP number (and not a "bigint").

(Since the number is an identifier and not something that actually involves any arithmetic I could argue that it's not an integer in the first place, just a string written with a particularly limited alphabet. But that's a database design issue for somewhere else.)
 [2020-08-15 03:46 UTC] jmuraca at gmail dot com
This ID large number format is how Texas represents utility account number. I can't change that.

I agree with the previous comment that I'd like to use it as a string as no math is performed. I'd like to use json_encode as my primary function to output json. And within that same output I'd like small integers to be represented as numbers, hence the use of JSON_NUMERIC_CHECK.

What I do not want is json_encode to change the large number from a string or int to scientific notation. By representing the number as a string, and then json_encode outputting in scientific notation, I am losing valuable information along the way.

My suggestion for JSON_BIGINT_AS_STRING solves this as it preserves my need for a string on a large number, which I happen to use as an ID, and allows smaller numbers to be represented as int and not string.
 [2020-08-15 04:14 UTC] requinix@php.net
> I agree with the previous comment that I'd like to use it as a string as no math is performed.
It's not even about that. The account number isn't actually a number. It's *numeric*. It's a value made up of the digits 0-9. It doesn't make sense to represent a phone number as an actual number, and it doesn't make sense to represent this account number as an actual number.

Besides, if you encode the account number as a JSON integer then you could easily have problems with other systems that can't handle it. It should remain as the string value you actually have.
https://www.google.com/search?q=site%3Astackoverflow.com+json+large+numbers

That also means you can't use JSON_NUMERIC_CHECK, like @cmb said. If you have number values that exist in PHP as strings (and thus would be encoded as strings) then you should cast/convert those as required.
https://3v4l.org/f3qUj

You also mentioned getting data from a database. Are number values coming back to you as strings? Switch to PDO, or if you're using MySQL and mysqli + mysqlnd then use the MYSQLI_OPT_INT_AND_FLOAT_NATIVE option.
https://www.php.net/manual/en/mysqli.options.php
 [2020-08-22 01:15 UTC] a at b dot c dot de
" I am losing valuable information along the way."
You were doing that long before you started JSON-encoding things, as you would have seen if you'd looked at the output of var_dump($data). But to make it more explicit, turn PHP's precision up to 24 significant figures and:

> echo 1008901020901566350119;
1008901020901566316544
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 17:01:58 2024 UTC