web-dev-qa-db-ja.com

JSONの文字列を使用して10進数を表すのはなぜですか

Paypal API などの一部のAPIは、JSONで文字列型を使用して10進数を表します。そう "7.47" の代わりに 7.47

Json数値型を使用するよりも、なぜ/いつこれが良い考えでしょうか? AFAIK数値型は無限の精度と科学的表記法を可能にします。

36
kag0

JSONの数値を文字列として転送する主な理由は、転送の精度やあいまいさの損失をなくすためです。

JSON仕様が数値の精度を指定していないのは事実です。これは、JSON番号の精度が無限であることを意味するものではありません。これは、数値精度が指定されていないことを意味します。つまり、JSON実装は、実装または目標に都合のよい数値精度を自由に選択できます。アプリケーションに特定の精度要件がある場合、この変動性が問題になる可能性があります。

一般に、数値のJSONエンコーディングでは精度の低下は見られませんが(1.7はニースで簡潔です)、受信側のJSON解析および中間表現で現れます。 JSON解析関数は1.7をIEEEの倍精度浮動小数点数にかなり合理的に解析します。ただし、有限長/有限精度の表現は、常に正確に表現できない数になります。無理数(piやeなど)は、有限システムでは正確に表現できません。 1.7は10進(基数10)表記の有限表現ですが、2進(基数2)では無理数-無限の数字列です。

したがって、1.7をメモリ内の浮動小数点数に解析し、その数値を出力すると、1.7ではなく1.69のようなものが返されます。

JSON 1.7値のコンシューマーは、固定小数点データ型や任意の精度の「string int」データ型を使用するなど、より高度な手法を使用してメモリ内の値を解析および保持できますが、これにより、一部の数値の変換で精度が低下します。そして現実には、ほとんどの状況でのメリットが低く、メモリとCPUのコストが高いため、このような極端な手段を必要とするJSONパーサーはほとんどありません。

したがって、正確な数値を消費者に送信したいが、値を一般的な内部数値表現に自動的に変換したくない場合、最善の策は数値を文字列として出荷し、消費者に正確に伝えることです数値演算を実行する必要がある場合に、その文字列を処理する方法。

例:一部のJSONプロデューサー(JRubyなど)では、BigIntegerの範囲と精度がIEEEの倍精度浮動小数点よりもはるかに大きいため、BigInteger値は文字列としてJSONに自動的に出力されます。 JSON数値として出力するためにBigInteger値を2倍に減らすと、しばしば有効数字が失われます。

また、JSON仕様( http://www.json.org/ )は、NaNと無限大(INF)がJSON数値に対して無効であることを明示的に示しています。これらのフリンジ要素を表現する必要がある場合は、JSON番号を使用できません。文字列またはオブジェクト構造を使用する必要があります。

最後に、数値データを文字列として送信することを選択できる別の側面があります。それは、表示フォーマットの制御です。先行ゼロと後続ゼロは、数値には関係ありません。 JSON数値2.10または004を送信すると、内部数値形式に変換された後、2.1および4として表示されます。

ユーザーに直接表示されるデータを送信する場合は、おそらく、画面上にお金の数字を10進数で揃えてきれいに並べたいと思うでしょう。そのための1つの方法は、クライアントに表示用のデータのフォーマットを行わせることです。それを行う別の方法は、サーバーに表示用のデータをフォーマットさせることです。クライアントが画面上に何かを表示するのは簡単かもしれませんが、これにより、クライアントも値の計算を行う必要がある場合、文字列から数値を抽出するのが難しくなります。

49
dthorpe

要約版

これが最も重要なポイントだと思うので、@ dthorpeの答えから引用するだけです。

また、JSON仕様( http://www.json.org/ )は、NaNと無限大(INF)がJSON数値に対して無効であることを明示的に示しています。これらのフリンジ要素を表現する必要がある場合は、JSON番号を使用できません。文字列またはオブジェクト構造を使用する必要があります。

3
Ole