rfc:json_numeric_as_string

This is an old revision of the document!


PHP RFC: JSON numeric as string

Introduction

JSON is a data format that is often used for data exchange between different platforms. These platforms can have different number representation which might lead to problems like type inconsistency or worse in loosing information (e.g. issue with double precision)

Proposal

The proposal is to introduce new options for dealing with this problem by converting the data to string.

Float to string conversion

The first option called JSON_FLOAT_AS_STRING will convert all float values to string.

Decoding

The idea is to convert all float values to string during decoding. That will prevent loosing precision.

Example
$data = json_decode('[1.23343224234, 1.34]', true, 512, JSON_FLOAT_AS_STRING);
var_dump($data);

will output:

array(2) {
  [0] =>
  string(13) "1.23343224234"
  [1] =>
  string(4) "1.34"
}
Issue

Currently the float precision will be always lost due to float conversion. This is especially problem if user needs to save the whole precision.

Encoding

The idea is to convert all float values to string during encoding.

Example
ini_set('precision', 12);
echo json_encode(arrray("a" => 1.23343224234, JSON_FLOAT_AS_STRING);

will output

{"a":"1.23343224234"}
Use case

Such use case can be useful when data are exported and will be parsed by the parser that might loose precision. For example when exporting to platforms using C float type.

Integer to string conversion

The second option called JSON_INT_AS_STRING will convert all int values to string.

Decoding

The idea is to convert all int values to string during decoding. That will prevent loosing precision.

Example
$data = json_decode('[23343224234, 34]', true, 512, JSON_INT_AS_STRING);
var_dump($data);

will output:

array(2) {
  [0] =>
  string(11) "23343224234"
  [1] =>
  string(2) "34"
}
Use case

This options might be useful when type consistency is required. The problem with precision is already resolved by JSON_BIGINT_AS_STRING. However when the numbers are on the edge of INT_MAX, then the result might be combination of string and integers.

Encoding

The idea is to convert all int values to string during encoding.

Example
echo json_encode(array( "a"=>123343224234), JSON_INT_AS_STRING);

will output

{"a":"123343224234"}
Use case

This options might be useful when exporting integers greater than 1 << 31 from 64bit platforms to 32bit platforms and the target JSON parser cannot handle such integers.

Backward Incompatible Changes

The code that defines JSON_FLOAT_AS_STRING and/or JSON_INT_AS_STRING will be broken. However the constants have JSON_ prefix so their usage is not recommended and it should be relatively safe addition.

Proposed PHP Version(s)

The proposed versions will be one of the voting options as some might consider it as not a self-contained feature.

There will be choice of 3 PHP version. The reason for that is that some might not consider the feature as self-contained addition.

  1. 5.6.next : this option will consider the feature/bug as a self-contained small addition. The precedence for this is adding JSON_PRESERVE_ZERO_FRACTION.
  2. 7.0: this option will consider the feature/bug as a self-contained and but does not consider feature important for 5.6
  3. 7.1: this option will consider the feature/bug as a non self-contained addition

New Constants

JSON_FLOAT_AS_STRING

  • json_decode - all float values will be decoded as string
    • It's often an issue for very large float values with many fractional digits that are coming from platforms that support larger float representation than double. In that case the conversion is lost and there is no way how to get it back. Converting the value to string keep the precision and resolves the problem.
  • json_encode - all float values will be encoded as string
    • Re-using the constant for encoder makes sense if PHP creates JSON for platform that support lower float type (e.g. C float) and the precision loss is not acceptable

JSON_INT_AS_STRING

  • json_decode - all int values will be decoded as string
    • When decoding numbers that that are on the edge of max integer, the JSON_BIGINT_AS_STRING can produce int type for some number and string types for others. This can be often inconvenient if the type consistency is required (e.g. further serialization/encoding for other platforms)
  • json_encode - all int values will be encoded as string
    • Re-using the constant for encoder makes sense if PHP creates JSON for platform that support lower int type (e.g. from 64bit to 32bit platform) and decoder on remote platform can't handle bigger integers

Open Issues

Better names?

Unaffected PHP Functionality

This RFC is related only to JSON extension.

Proposed Voting Choices

There will be 5 voting:

  1. whether include JSON_FLOAT_TO_STRING for decoding
  2. whether include JSON_FLOAT_TO_STRING for encoding
  3. whether include JSON_INT_TO_STRING for decoding
  4. whether include JSON_INT_TO_STRING for encoding
  5. choice of the version (see above)

50%+1 majority (see voting) for all votings

Patches and Tests

The patch is really simple and will be implemented by the author of this RFC if it's accepted.

References

Rejected Features

None

rfc/json_numeric_as_string.1431022730.txt.gz · Last modified: 2017/09/22 13:28 (external edit)