Почему вы используете строку в JSON для представления десятичного числа

Некоторые API, такие как paypal API, используют тип строки в JSON для представления десятичного числа. Итак "7.47" вместо 7.47.

Почему/когда это будет хорошей идеей по использованию типа значения json number? AFAIK тип числового значения допускает бесконечную точность, а также научную нотацию.

Ответ 1

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

Верно, что спецификация JSON не указывает точность для числовых значений. Это не означает, что номера JSON имеют бесконечную точность. Это означает, что числовая точность не указана, что означает, что реализация JSON позволяет выбирать любую цифровую точность, удобную для их реализации или целей. Именно эта изменчивость может быть больной, если ваше приложение имеет конкретные требования к точности.

Потеря точности обычно не очевидна в кодировке JSON для числового значения (1.7 является красивой и кратким), но проявляется в синтаксическом анализе JSON и промежуточных представлениях на принимающей стороне. Функция разбора JSON вполне разумно проанализирует 1.7 в число с плавающей запятой двойной точности IEEE. Однако представления конечной длины/конечной точности всегда будут отображаться в числах, которые не могут быть точно представлены. Иррациональные числа (например, pi и e) никогда не могут быть точно представлены в конечной системе. 1.7 имеет конечное представление в десятичной (базовая 10) нотации, но в двоичном (основание 2) это иррациональное число - бесконечная серия цифр.

Итак, разбор 1.7 в число с плавающей запятой в памяти, тогда распечатка номера, скорее всего, вернет что-то вроде 1.69 - не 1.7.

Потребители значения JSON 1.7 могут использовать более сложные методы для анализа и сохранения значения в памяти, например, с использованием типа данных с фиксированной точкой или типа данных типа string с произвольной точностью, но это не будет полностью устранять призрак потери точности в преобразовании для некоторых чисел. И на самом деле очень мало парней JSON беспокоятся о таких экстремальных мерах, поскольку преимущества для большинства ситуаций низкие, а затраты памяти и процессора высоки.

Итак, если вы хотите отправить точное числовое значение потребителю, и вы не хотите, чтобы автоматическое преобразование значения в типичное внутреннее числовое представление, лучшим выбором является отправка числового значения в виде строки и указание потребитель точно, как эта строка должна обрабатываться, если и когда на ней должны выполняться числовые операции.

Например: у некоторых производителей JSON (JRuby, для одного) значения BigInteger автоматически выводятся в JSON в виде строк, в основном потому, что диапазон и точность BigInteger намного больше, чем плавающий двойной точности IEEE. Уменьшение значения BigInteger в два раза для вывода в виде номера JSON часто теряет значительную цифру.

Кроме того, спецификация JSON (http://www.json.org/) явно указывает, что значения NaN и Infinities (INF) недействительны для числовых значений JSON. Если вам нужно выразить эти элементы бахромы, вы не можете использовать номер JSON. Вы должны использовать структуру строк или объектов.

Наконец, существует еще один аспект, который может привести к выбору отправки числовых данных в виде строк: управление форматированием отображения. Ведущие нули и конечные нули несущественны для числового значения. Если вы отправите значение номера JSON 2.10 или 004, после преобразования во внутреннюю числовую форму они будут отображаться как 2.1 и 4.

Если вы отправляете данные, которые будут отображаться непосредственно пользователю, вы, вероятно, хотите, чтобы ваши денежные цифры хорошо выстроились на экране с десятичной точностью. Один из способов сделать это - заставить клиента отвечать за форматирование данных для отображения. Другой способ сделать это - предоставить серверу формат данных для отображения. Упрощение для клиента, чтобы отображать информацию на экране, возможно, но это может затруднить извлечение числового значения из строки, если клиенту также необходимо выполнить вычисления по значениям.

Ответ 2

Обобщенная версия

Просто процитировав ответ @dthorpe, так как я думаю, что это самый важный момент:

Кроме того, спецификация JSON (http://www.json.org/) явно указывает, что значения NaN и Infinities (INF) недействительны для числовых значений JSON. Если вам нужно выразить эти элементы бахромы, вы не можете использовать номер JSON. Вы должны использовать структуру строк или объектов.