PHP: как кодировать числа бесконечности или NaN в JSON?

По-видимому, бесконечность и NaN не являются частью спецификации JSON, поэтому этот PHP-код:

$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";

Производит это:

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}

Есть ли способ правильно закодировать эти числа без написания собственной функции json_encode()? Может быть, какое-то обходное решение?


person Septagram    schedule 27.11.2012    source источник


Ответы (5)


Согласно спецификации JSON, значения Infinity или NaN отсутствуют: http://json.org/

Обходные пути:

  1. Откажитесь от использования JSON (чистого JSON) и напишите свою собственную функцию json_encode, которая будет обрабатывать INF/NAN (преобразовывая в «Infinity» и «NaN» соответственно), и убедитесь, что вы анализируете JSON, используя что-то вроде result = eval('(' + json + ')'); на стороне клиента.

  2. Предварительно конвертируйте ваши значения IFN/NAN в строковые значения ("Infinity" и "NaN"), и когда вы собираетесь работать с этими значениями в JavaScript, используйте следующую конструкцию: var number1 = (+numbers.positive_infinity);. Это преобразует строковое значение «Бесконечность» в числовое представление Infinity.

person mdevils    schedule 27.11.2012
comment
Вы можете дополнительно использовать JSON.stringify(json, replacer), где replacer — это некоторая функция, которая заменяет Infinity, NaN и т. д. в их строковые представления (см. 5c9423841fa3" rel="nofollow noreferrer">levelup.gitconnected.com/ для примера) - person Ollie; 31.12.2019

Вы правы насчет спецификации JSON:

Числовые значения, которые не могут быть представлены в виде последовательностей цифр (например, Infinity и NaN), не допускаются.

Решение также должно исходить из спецификации, поскольку пользовательский кодировщик «JSON» в любом случае не будет генерировать действительный JSON (вам также придется написать собственный декодер, и тогда вы и потребители ваших данных будете вынуждены использовать его до тех пор, пока конец времени).

Вот что спецификация допускает для значений:

Значение JSON ДОЛЖНО быть объектом, массивом, числом или строкой или одним из следующих трех литеральных имен:

false null true

Таким образом, любой обходной путь, который включает в себя легальный JSON вместо пользовательского протокола, подобного JSON, будет включать использование чего-то другого вместо чисел.

Одним из разумных вариантов было бы использовать строки "Infinity" и "NaN" для этих крайних случаев.

person Jon    schedule 27.11.2012
comment
+1 за цитирование спецификации и упоминание литералов. Однако принимая другой ответ, потому что он предлагает способ преобразовать их обратно в числа. - person Septagram; 27.11.2012

На мой взгляд, это большой недостаток JSON. Различные кодировщики JSON обрабатывают это по-разному, краткий обзор можно найти здесь: http://lavag.org/topic/16217-cr-json-labview/?p=99058

Одно из решений состоит в том, чтобы закодировать +inf как +1e9999, так как в большинстве декодеров это будет естественным образом переполняться +inf, и то же самое с -inf как -1e9999. NaN намного сложнее.

person emilk    schedule 31.01.2013

В качестве обновления для читателей этого вопроса для более новых версий PHP >= 5.5.0, чтобы получить значения INF или NAN из json_encode для кодирования как 0, а не json_encode вообще не выводить, добавьте JSON_PARTIAL_OUTPUT_ON_ERROR.

Например: json_encode($data, JSON_NUMERIC_CHECK | JSON_PARTIAL_OUTPUT_ON_ERROR);

person Sean Fahey    schedule 26.07.2017

Предупреждение, упомянутое выше, есть официальная ошибка, о которой сообщается в документации php.

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

person Manjunath Reddy    schedule 26.12.2014