データ型のさまざまな癖とローカリゼーションを念頭に置いて、Webサービスがアプリケーションと金銭的価値をやり取りするための最良の方法は何ですか?どこかに標準はありますか?
最初に考えたのは、単純に数値型を使用することでした。例えば
"amount": 1234.56
通貨の計算に浮動小数点データ型を使用する場合、精度の不足と丸め誤差に関する問題について多くの議論を見てきましたが、計算ではなく値を送信するだけなので、問題ではありません。
EventBriteのJSON通貨仕様 このようなものを指定します:
{
"currency": "USD",
"value": 432,
"display": "$4.32"
}
浮動小数点値を回避するためのBravoですが、今度は別の問題に直面します:保持できる最大の数は?
1つのコメント (それが本当かどうかはわかりませんが、合理的と思われます)JSONの実装方法はさまざまなので、32ビットの符号付き整数が最適だと主張しています。 32ビットの符号付き整数が保持できる最大値は2147483647です。値を小単位で表すと、21,474,836.47ドルになります。 2,100万ドルは膨大な数のように思えますが、一部のアプリケーションがそれより大きい値で動作する必要があることは考えられません。この問題は、1,000のマイナーユニットがメジャーユニットを構成する通貨、または通貨が米ドルよりも価値のない通貨で悪化します。たとえば、チュニジアディナールは1,000ミリムに分割されます。 2147483647 milim、または2147483.647 TNDは1,124,492.04ドルです。場合によっては、100万ドルを超える値が使用される可能性がさらに高くなります。別の例:ベトナムドンのサブユニットはインフレーションによって役に立たなくなったので、メジャーユニットを使用します。 2147483647 VNDは98,526.55ドルです。多くのユースケース(銀行残高、不動産価値など)はそれよりもかなり高いと確信しています。 (ただし、EventBriteは、チケットの価格がそれほど高いことを心配する必要はないでしょう!)
値を文字列として通信することでこの問題を回避する場合、文字列はどのようにフォーマットする必要がありますか?国/地域によって形式が大幅に異なります。通貨記号、金額の前後に記号が現れるかどうか、記号と金額の間にスペースがあるかどうか、カンマまたはピリオドを使用して小数点を区切る場合、カンマ負の値を示すために、千単位の区切り記号、括弧、またはマイナス記号として使用されます。
アプリが動作しているロケール/通貨を知っている場合、次のような値を伝えます
"amount": "1234.56"
前後に、アプリが金額を正しくフォーマットすることを信頼しますか? (また、10進数値を避け、最小の通貨単位で値を指定する必要がありますか?または、メジャーとマイナーの単位を異なるプロパティにリストする必要がありますか?
または、サーバーは生の値とフォーマットされた値を提供する必要がありますか?
"amount": "1234.56"
"displayAmount": "$1,234.56"
または、サーバーは生の値と通貨コードを提供し、アプリにフォーマットさせますか? "amount": "1234.56" "currencyCode": "USD"どちらの方法を使用する場合でも、サーバーとの間で双方向に使用する必要があると思います。
標準を見つけることができませんでした-答えがありますか、またはこれを定義するリソースを指定できますか?よくある問題のようです。
それが最善の解決策であるかどうかはわかりませんが、私が今しようとしているのは、次のように、小数点以外の書式なしの文字列として値を渡すことです:
"amount": "1234.56"
アプリはそれを簡単に解析できます(そして、それをdouble、BigDecimal、int、またはアプリ開発者が浮動小数点演算に最適だと思う方法に変換します)。アプリは、ロケールと通貨に応じて表示する値をフォーマットする必要があります。
この形式は、大きく膨らんだ大きな数値、小数点以下3桁の数値、小数値をまったく含まない数値など、他の通貨値に対応できます。
もちろん、これは、アプリが既に使用されているロケールと通貨を知っていることを前提としています(別の呼び出し、アプリの設定、またはローカルデバイスの値から)。それらを呼び出しごとに指定する必要がある場合、別のオプションは次のようになります。
"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
これらを1つのJSONオブジェクトにまとめたいと思っていますが、JSONフィードにはさまざまな目的のために複数の金額があり、通貨設定を1回指定するだけで済みます。もちろん、リストされている量ごとに異なる場合は、次のように一緒にカプセル化するのが最善です。
{
"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
}
別の議論の余地のあるアプローチは、サーバーが生の量とフォーマットされた量を提供することです。 (もしそうなら、すべて同じ概念を定義するフィードに複数のプロパティを持たせるのではなく、オブジェクトとしてカプセル化することをお勧めします):
{
"displayAmount":"$1,234.56",
"calculationAmount":"1234.56"
}
ここでは、より多くの作業がサーバーにオフロードされます。また、条件のテストなどに簡単に解析可能な値を提供しながら、数値の表示方法の異なるプラットフォームおよびアプリ間で一貫性を確保します。
ただし、アプリが計算を実行し、結果をユーザーに表示する必要がある場合はどうなりますか?表示用に番号をフォーマットする必要があります。この回答の上部にある最初の例でも同様に行って、書式設定をアプリに制御させることができます。
少なくとも私の考えです。私はこの分野で確固たるベストプラクティスや研究を見つけることができなかったので、私が指摘していないより良い解決策や潜在的な落とし穴を歓迎します。
知る限り、JSONには「通貨」標準はありません-これは初歩的なタイプに基づく標準です。考慮したいのは、一部の通貨には小数部がない(ギニアフラン、インドネシアルピア)、一部は1000分の1に分割できる(バーレーンディナール)ため、小数点以下2桁を想定したくないということです。 Iranian Realの場合、200万ドルはあなたを大きく引き離せないので、整数ではなく倍精度を扱う必要があると思います。一般的な国際モデルをお探しの場合、ハイパーインフレーションのある国では2年ごとに通貨を変更して値を1,000,000(または100ミル)で除算することが多いため、通貨コードが必要になります。歴史的には、ブラジルとイランの両方がこれを行ったと思います。
通貨コードの参照(およびその他の適切な情報)が必要な場合は、こちらをご覧ください: https://Gist.github.com/Fluidbyte/2973986
オン 開発者ポータル-APIガイドライン-通貨 興味深い提案を見つけることができます。
"price" : {
"amount": 40,
"currency": "EUR"
}
単なる文字列よりも生成とフォーマットが少し難しいですが、これを達成するための最もクリーンで意味のある方法だと思います:
number
JSON
タイプを使用ここでJSON形式が提案されました: https://pattern.yaas.io/v2/schema-monetary-amount.json
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "Monetary Amount",
"description":"Schema defining monetary amount in given currency.",
"properties": {
"amount": {
"type": "number",
"description": "The amount in the specified currency"
},
"currency": {
"type": "string",
"pattern": "^[a-zA-Z]{3}$",
"description": "ISO 4217 currency code, e.g.: USD, EUR, CHF"
}
},
"required": [
"amount",
"currency"
]
}
別の 通貨形式に関連する質問 正しいか間違っていると指摘されていますが、これは基本単位を持つ文字列のようなものです:
{
"price": "40.0"
}
金額は文字列として表す必要があります。
文字列を使用するという考え方は、jsonを使用するクライアントは、BigDecimal
などの10進数型に解析して、浮動小数点の不正確さを回避する必要があるということです。
ただし、システムの一部が浮動小数点も回避する場合にのみ意味があります。バックエンドがデータを渡すだけで計算を行わない場合でも、浮動小数点を使用すると、最終的に(プログラムで)表示されるものが(jsonで)表示されなくなります。
そして、ソースがデータベースであると仮定すると、正しいタイプで保存されたデータを持つことが重要です。データが既に浮動小数点として保存されている場合、技術的に不正確な情報を渡すため、その後の変換やキャストは無意味になります。