一尘不染

为什么要在JSON中使用字符串表示十进制数字

json

一些API(例如paypal
API)
在JSON中使用字符串类型表示十进制数字。所以"7.47"代替7.47

为什么/何时使用json数字值类型是个好主意?AFAIK数字值类型允许无限精度和科学计数法。


阅读 422

收藏
2020-07-27

共1个答案

一尘不染

将JSON中的数字值作为字符串传输的主要原因是为了消除传输中的精度或歧义性。

的确,JSON规范未指定数字值的精度。这并不意味着JSON数字具有无限的精度。这意味着未指定数值精度,这意味着JSON实现可以自由选择对其实现或目标而言更方便的数值精度。如果您的应用程序具有特定的精度要求,那么这种可变性可能会让人感到痛苦。

精度损失通常在数值的JSON编码中并不明显(1.7很好且简洁),但在接收端的JSON解析和中间表示中表现出来。JSON解析函数可以相当合理地将1.7解析为IEEE双精度浮点数。但是,有限长度/有限精度的十进制表示将始终遇到数字,其十进制扩展不能表示为有限的数字序列:

  1. 无理数(例如pi和e)

  2. 1.7具有以10为基础的表示法的有限表示形式,但是以二进制(以2为基础)的表示法,不能正确编码1.7。即使二进制数几乎无限,您也只会接近1.7,但永远不会精确到1.7。

因此,将1.7解析为内存中的浮点数,然后输出该数字可能会返回1.69-而不是1.7。

JSON 1.7值的使用者可以使用更复杂的技术来解析该值并将其保留在内存中,例如使用定点数据类型或任意精度的“ string
int”数据类型,但这不会完全消除某些数字转换精度下降。现实情况是,很少有JSON解析器会受到如此极端的措施的困扰,因为在大多数情况下,这样做的好处很低,而内存和CPU的成本却很高。

因此,如果您希望将精确的数值发送给使用者,并且不希望将该值自动转换为典型的内部数值表示形式,那么最好的选择是将数值作为字符串发送出去,并准确告知使用者如果以及何时需要对其执行数字运算,应如何处理该字符串。

例如:在某些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。

如果要发送的数据将直接显示给用户,则可能希望您的钱数字在屏幕上对齐,小数点对齐。一种方法是让客户端负责格式化要显示的数据。另一种方法是让服务器格式化数据以供显示。客户端可能更容易在屏幕上显示内容,但是如果客户端还需要对值进行计算,则这可能会使从字符串中提取数字值变得困难。

2020-07-27