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

Cha*_*ltz 27 json api-design currency

考虑到数据类型的各种怪癖和本地化,Web服务与应用程序之间传递货币价值的最佳方式是什么?某处有标准吗?

我的第一个想法是简单地使用数字类型.例如

"amount": 1234.56
Run Code Online (Sandbox Code Playgroud)

在使用浮点数据类型进行货币计算时,我已经看到很多关于缺乏精度和舍入误差的问题的论点 - 但是,我们只是传递值而不是计算,所以这无关紧要.

EventBrite的JSON货币规范指定如下:

{
"currency": "USD", 
"value": 432, 
"display": "$4.32"
}
Run Code Online (Sandbox Code Playgroud)

Bravo用于避免浮点值,但现在我们遇到另一个问题:我们可以容纳的最大数字是多少?

一条评论(我不知道它是否属实,但似乎是合理的)声称,由于数字实现在JSON中有所不同,因此您可以期待的最好的是32位有符号整数.32位有符号整数可以容纳的最大值是2147483647.如果我们表示次要单位中的值,那么是21,474,836.47美元.2100万美元似乎是一个巨大的数字,但是某些应用程序可能需要使用大于此值的值,这并不是不可思议的.对于1000个未成年单位成为主要单位的货币,或者货币价值低于美元的货币,问题会变得更严重.例如,突尼斯第纳尔分为1,000毫米.2147483647 milim,或2147483.647 TND是$ 1,124,492.04.在某些情况下,更有可能超过100万美元的价值.另一个例子:越南盾的子单位因通货膨胀而变得无用,所以让我们只使用主要单位.2147483647越南盾是98,526.55美元.我相信很多用例(银行存款,房地产价值等)远高于此.(EventBrite可能不必担心票价会那么高!)

如果我们通过将值作为字符串传递来避免该问题,那么字符串应该如何格式化?不同的国家/地区具有截然不同的格式 - 不同的货币符号,无论符号出现在金额之前还是之后,无论是否在符号和金额之间有空格,如果使用逗号或句点来分隔小数,如果逗号用作千位分隔符,括号或减号来表示负值,可能还有更多我不知道的值.

如果应用知道它正在使用的语言环境/货币,请传达类似的值

"amount": "1234.56"
Run Code Online (Sandbox Code Playgroud)

来回,并相信应用程序正确格式化金额?(另外:是否应避免使用小数值,以及以最小货币单位指定的值?或者主要和次要单位是否应列在不同的属性中?)

或者服务器应该提供原始值和格式化值?

"amount": "1234.56"
"displayAmount": "$1,234.56"
Run Code Online (Sandbox Code Playgroud)

或者服务器应该提供原始值和货币代码,并让应用程序格式化它?"amount":"1234.56""currencyCode":"USD"我假设使用的方法应该在两个方向上使用,与服务器之间进行传输.

我一直无法找到标准 - 您是否有答案,或者可以指向我定义此资源的资源?这似乎是一个普遍的问题.

Cha*_*ltz 6

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

"amount": "1234.56"
Run Code Online (Sandbox Code Playgroud)

应用程序可以轻松解析(并将其转换为double,BigDecimal,int或app开发人员认为最适合浮点运算的任何方法).该应用程序将负责根据区域设置和货币格式化显示的值.

此格式可以容纳其他货币值,无论是高度膨胀的大数字,小数点后三位数字,完全没有小数值的数字等.

当然,这将假设应用程序已经知道所使用的区域设置和货币(来自另一个调用,应用程序设置或本地设备值).如果需要为每个呼叫指定那些,另一个选项是:

"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
Run Code Online (Sandbox Code Playgroud)

我很想将它们转换为一个JSON对象,但是JSON提要可能有多个用于不同目的的数量,然后只需要指定一次货币设置.当然,如果列出的每个数量都有所不同,那么最好将它们封装在一起,如下所示:

{
"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
}
Run Code Online (Sandbox Code Playgroud)

另一个值得商榷的方法是服务器提供原始数量和格式化数量.(如果是这样,我建议将其封装为一个对象,而不是在所有定义相同概念的Feed中具有多个属性):

{
"displayAmount":"$1,234.56",
"calculationAmount":"1234.56"
}
Run Code Online (Sandbox Code Playgroud)

在这里,更多的工作被卸载到服务器.它还确保了不同平台和应用程序在数字显示方式上的一致性,同时仍为条件测试等提供了易于解析的价值.

但是,它确实存在问题 - 如果应用程序需要执行计算然后向用户显示结果,该怎么办?它仍然需要格式化显示的数字.也可以使用此答案顶部的第一个示例,并让app控制格式.

这至少是我的想法.我一直无法在这方面找到任何可靠的最佳实践或研究,所以我欢迎更好的解决方案或潜在的陷阱,我没有指出.


Pau*_*rey 5

AFAIK,JSON 中没有“货币”标准 - 它是基于基本类型的标准。您可能需要考虑的是,某些货币没有小数部分(几内亚法郎、印度尼西亚卢比),而某些货币可以分为千分之一(巴林第纳尔) - 因此您不想假设两位小数。对于伊朗雷亚尔来说,200 万美元不会让你走得太远,所以我希望你需要处理双精度数而不是整数。如果您正在寻找通用的国际模型,那么您将需要一个货币代码,因为恶性通货膨胀的国家通常每两年更换一次货币,将价值除以 1,000,000(或 100 mill)。我认为,历史上巴西和伊朗都曾这样做过。

如果您需要货币代码的参考(以及一些其他好的信息),请查看此处: https: //gist.github.com/Fluidbyte/2973986