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
 [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

Add a Patch

Pull Requests

Add a Pull Request

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: Thu Mar 28 10:01:26 2024 UTC