Question

Apparently, infinity and NaN are not a part of JSON specification, so this PHP code:

$numbers = array();
$numbers ['positive_infinity'] = +INF;
$numbers ['negative_infinity'] = -INF;
$numbers ['not_a_number'] = NAN;
$array_print = print_r ($numbers, true);
$array_json = json_encode ($numbers);
echo "\nprint_r(): $array_print";
echo "\njson_encode(): $array_json";

Produces this:

PHP Warning:  json_encode(): double INF does not conform to the JSON spec, encoded as 0 in /home/septi/test.php on line 8
PHP Warning:  json_encode(): double -INF does not conform to the JSON spec, encoded as 0 in /home/septi/test.php on line 8
PHP Warning:  json_encode(): double NAN does not conform to the JSON spec, encoded as 0 in /home/septi/test.php on line 8

print_r(): Array
(
    [positive_infinity] => INF
    [negative_infinity] => -INF
    [not_a_number] => NAN
)

json_encode(): {"positive_infinity":0,"negative_infinity":0,"not_a_number":0}

Is there any way to correctly encode these numbers without writing my own json_encode() function? Maybe some workaround?

Était-ce utile?

La solution 2

According to JSON spec, there is no Infinity or NaN values: http://json.org/

Workarounds:

  1. Reject using JSON (pure JSON), and write your own json_encode function, which will handle INF/NAN (converting to "Infinity" and "NaN" respectively), and make sure you are parsing JSON using something like result = eval('(' + json + ')'); on the client side.

  2. Pre convert your IFN/NAN values into string values ('Infinity' and 'NaN'), and when you are going to operate with those values in JavaScript, use the following construction: var number1 = (+numbers.positive_infinity);. This will convert string value 'Infinity' into numeric Infinity representation.

Autres conseils

You are right about the JSON spec:

Numeric values that cannot be represented as sequences of digits (such as Infinity and NaN) are not permitted.

The solution must also come from the spec, since a custom "JSON" encoder would not produce valid JSON anyway (you would have to write a custom decoder as well, and then you and consumers of your data would be forced to use that until the end of time).

Here' what the spec allows for values:

A JSON value MUST be an object, array, number, or string, or one of the following three literal names:

false null true

So, any workaround that involves legal JSON instead of a custom JSON-like protocol would involve using something else instead of numbers.

One reasonable option would be to use the strings "Infinity" and "NaN" for these edge cases.

This is in my opinion a big shortcoming of JSON. Different JSON encoders handle this differently, a quick overview can be found here: http://lavag.org/topic/16217-cr-json-labview/?p=99058

One solution is to encode +inf as +1e9999 as that will naturally overflow to +inf in most decoders, and same with -inf as -1e9999. NaN is much harder.

As an update to readers of this question for newer versions of PHP >= 5.5.0, to get INF or NAN values from json_encode to be encoded as 0 rather than json_encode failing to output at all, add the JSON_PARTIAL_OUTPUT_ON_ERROR option.

As an example: json_encode($data, JSON_NUMERIC_CHECK | JSON_PARTIAL_OUTPUT_ON_ERROR);

The warning mentioned above, there is official bug reported in php documentation.

https://bugs.php.net/bug.php?id=64695

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top