JSON中格式化货币值的标准是什么?

c90pui9n  于 2022-12-20  发布在  其他
关注(0)|答案(5)|浏览(196)

考虑到数据类型和本地化的各种怪癖,Web服务与应用程序之间传递货币价值的最佳方式是什么?是否有某种标准?
我首先想到的是简单地使用数字类型。

"amount": 1234.56

我看到过许多关于在使用浮点数据类型进行货币计算时缺乏精度和舍入错误的争论--然而,我们只是在传输值,而不是计算,所以这不应该是问题。
EventBrite's JSON currency specifications指定如下内容:

{
"currency": "USD", 
"value": 432, 
"display": "$4.32"
}

避免使用浮点值非常好,但现在我们遇到了另一个问题:我们最多能容纳多少人?
一条评论(我不知道这是不是真的,但看起来很合理)声称,由于JSON中的数字实现各不相同,因此您所能期望的最佳值是一个32位有符号整数。一个32位有符号整数所能容纳的最大值是2147483647。如果我们以次要单位表示值,那就是21,474,836.47美元。2100万美元看起来是一个巨大的数字,但某些应用程序可能需要处理大于该值的值,这并非不可想象。如果货币的1,000个小单位构成一个大单位,或者货币的价值低于美元,则问题会变得更严重。例如,突尼斯第纳尔被分为1,000 milim。2147483647 milim,或2147483.647 TND为$1,124,492.04。在某些情况下,甚至更有可能使用超过$100万的值。另一个示例:越南盾的子单位由于通货膨胀而变得毫无用处,所以让我们使用主要单位。2147483647越南盾是98,526.55美元。我敢肯定,许多用例(银行余额、房地产价值等)都大大高于这个数字。(不过,EventBrite可能不必担心票价那么高!)
如果我们通过将值作为字符串进行通信来避免这个问题,那么该如何设置字符串的格式呢?不同的国家/地区具有完全不同的格式-不同的货币符号、符号出现在金额之前还是之后、符号与金额之间是否有空格、是否使用逗号或句点分隔小数点、是否使用逗号作为千位分隔符、括号或减号表示负值,可能还有更多我不知道的值。
如果应用程序知道它使用的是哪种语言环境/货币,则应传递如下值

"amount": "1234.56"

并信任该应用程序能够正确格式化金额?(另请参阅:是否应该避免使用十进制值,并以最小货币单位指定值?或者是否应该在不同的属性中列出主要单位和次要单位?)
或者服务器应该提供原始值和格式化值?

"amount": "1234.56"
"displayAmount": "$1,234.56"

或者,服务器是否应该提供原始值和货币代码,并让应用对其进行格式化?"金额":"1234.56""货币代码":"USD"我认为无论使用哪种方法,都应该在两个方向上使用,即与服务器之间的传输。
我一直找不到标准--你有答案吗,或者可以给我指一个定义这个的资源吗?这似乎是一个常见的问题。

r55awzrz

r55awzrz1#

我不知道这是否是最好的解决方案,但我现在尝试的是将值作为字符串传递,除了小数点之外,不带任何格式,如下所示:

"amount": "1234.56"

应用程序可以很容易地解析它(并将其转换为double、BigDecimal、int或应用程序开发人员认为最适合浮点运算的任何方法),应用程序将负责根据区域设置和货币设置显示值的格式。
这种格式可以容纳其他货币值,无论是高度膨胀的大数、小数点后有三位数的数字,还是根本没有小数值的数字,等等。
当然,这需要假设应用已经知道所使用的区域设置和货币(来自另一个调用、应用设置或本地设备值)。如果需要在每个调用中指定这些内容,另一个选项是:

"amount": "1234.56",
"currency": "USD",
"locale": "en_US"

我很想将这些内容整合到一个JSON对象中,但是一个JSON提要可能有多个金额用于不同的目的,因此只需要指定一次货币设置。当然,如果列出的每个金额都不同,那么最好将它们封装在一起,如下所示:

{
"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
}

另一个有争议的方法是让服务器提供原始金额和格式化金额(如果是这样,我建议将其封装为一个对象,而不是在一个提要中包含多个属性,这些属性都定义了同一个概念):

{
"displayAmount":"$1,234.56",
"calculationAmount":"1234.56"
}

在这里,更多的工作被转移到服务器上,它还确保了不同平台和应用在如何显示数字方面的一致性,同时仍然为条件测试等提供了一个易于解析的值。
然而,这确实留下了一个问题--如果应用程序需要执行计算,然后将结果显示给用户怎么办?它仍然需要格式化数字以供显示。不妨使用本答案顶部的第一个示例,并给予应用程序控制格式化。
至少这是我的想法,我在这个领域还没有找到任何可靠的最佳实践或研究,所以我欢迎更好的解决方案或我没有指出的潜在陷阱。

wa7juj8i

wa7juj8i2#

当然,JSON中没有“货币”标准--它是基于基本类型的标准。您可能需要考虑的是,有些货币没有小数部分(几内亚法郎、印度尼西亚卢比),有些可以分为千分之一(巴林第纳尔)-因此,您不想假设两个小数位。对于伊朗真实的$200万不会让你走得很远,所以我希望你需要处理双精度数而不是整数。如果你正在寻找一个通用的国际模型,那么你将需要一个货币代码,因为恶性通货膨胀的国家经常每两年更换一次货币,以将价值除以1000,000(或100百万)。历史上巴西和伊朗都这样做过,我想。
如果您需要货币代码的参考(以及其他一些有用的信息),请查看这里:https://gist.github.com/Fluidbyte/2973986

xdyibdwo

xdyibdwo3#

金额应表示为字符串。
使用string的思想是,任何使用json的客户机都应该将其解析为十进制类型,例如BigDecimal,以避免浮点不精确。
然而,只有当系统的任何部分也避免使用浮点时,它才有意义,即使后端只是传递数据而不做任何计算,使用浮点最终会导致你所看到的(在程序中)不是你所得到的(在json上)。
假设数据源是一个数据库,那么用正确的类型存储数据是很重要的,如果数据已经存储为浮点型,那么任何后续的转换或转换都将是毫无意义的,因为从技术上讲,它将传递不精确。

ego6inou

ego6inou4#

ON Dev Portal - API指南-货币您可能会发现有趣的建议:

"price" : {
 "amount": 40,
 "currency": "EUR"
}

生成& format比生成一个字符串要困难一些,但我觉得这是实现它的最干净和最有意义的方法:
1.取消金额和币种
1.使用numberJSON类型
这里建议使用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"
    ]
}

另一个questions related to currency format指出,不管对错,实践更像是一个带有基本单位的字符串:

{
    "price": "40.0"
}
gupuwyp2

gupuwyp25#

可能没有任何官方标准,我们的产品使用以下结构:

"amount": {
    "currency": "EUR",
    "scale": 2,
    "value": 875
}

上例表示金额€8.75。
货币定义为字符串(值应符合ISO4217),小数位数和值为整数,“小数位数”的含义很明显,这种结构解决了货币没有小数、小数位数不规范等问题。

相关问题