在 JSON 中传递美元金额的最佳实践是啥?

Posted

技术标签:

【中文标题】在 JSON 中传递美元金额的最佳实践是啥?【英文标题】:What are the best practices passing dollar amounts in JSON?在 JSON 中传递美元金额的最佳实践是什么? 【发布时间】:2017-12-26 14:56:48 【问题描述】:

在 JSON 中传递美元金额的最佳做法是什么?

将金额作为字符串还是浮点数传递?或其他?

我们有点担心客户端(ios / android / Web)上显示的舍入错误,或者一个客户端上显示的值可能与另一个客户端不同。

【问题讨论】:

美分,所以你可以使用整数。 【参考方案1】:

Effective Java,第 2 版 Joshua Bloch 说

float 和 double 类型特别不适合货币计算,因为不可能将 0.1(或任何其他十的负幂)表示为 float 或 double。

例如,假设您有 1.03 美元,而您花了 42 美分。你还剩多少钱?

System.out.println(1.03 - .42); 打印出 0.6100000000000001。

解决这个问题的正确方法是使用 BigDecimal、int 或 long。

永远不要在浮点变量中保存货币值。浮点数不适用于货币使用定点或十进制值。

最好以几种不同的格式提供货币代码和相同的值。考虑这个典型的响应为 0.00234

"amount": 
  "currency": "USD",
  "decimal": 0.00234,
  "integer": 234000,
  "integer_scale": 8,
  "pretty": "\u0e3f 0.00234 BTC",
  "string": "0.00234"

您可以选择使用任何提供的数字格式。

十进制:这是一个十进制数 字符串:与十进制相同但被引用,因此您的 JSON 库认为它是一个字符串。 pretty:准备好向用户展示的字符串。包括适当的货币符号和货币代码。 货币:货币的 3 个字母代码。

以下是两个示例 API:

1 - JSON 中的通用货币代码


    "USD": 
        "symbol": "$",
        "name": "US Dollar",
        "symbol_native": "$",
        "decimal_digits": 2,
        "rounding": 0,
        "code": "USD",
        "name_plural": "US dollars"
    ,
    "CAD": 
        "symbol": "CA$",
        "name": "Canadian Dollar",
        "symbol_native": "$",
        "decimal_digits": 2,
        "rounding": 0,
        "code": "CAD",
        "name_plural": "Canadian dollars"
    ,
    "EUR": 
        "symbol": "€",
        "name": "Euro",
        "symbol_native": "€",
        "decimal_digits": 2,
        "rounding": 0,
        "code": "EUR",
        "name_plural": "euros"
    

https://gist.github.com/Fluidbyte/2973986

2 - 修复程序 API

http://api.fixer.io/latest


    "base": "EUR",
    "date": "2017-07-28",
    "rates": 
        "AUD": 1.4732,
        "BGN": 1.9558,
        "BRL": 3.7015,
        "CAD": 1.4712,
        "CHF": 1.1357,
        "CNY": 7.9087,
        "CZK": 26.048,
        "DKK": 7.4364,
        "GBP": 0.89568,
        "HKD": 9.1613,
        "HRK": 7.412,
        "HUF": 304.93,
        "IDR": 15639,
        "ILS": 4.1765,
        "INR": 75.256,
        "JPY": 130.37,
        "KRW": 1317.6,
        "MXN": 20.809,
        "MYR": 5.0229,
        "NOK": 9.3195,
        "NZD": 1.5694,
        "php": 59.207,
        "PLN": 4.2493,
        "RON": 4.558,
        "RUB": 69.832,
        "SEK": 9.5355,
        "SGD": 1.5947,
        "THB": 39.146,
        "TRY": 4.1462,
        "USD": 1.1729,
        "ZAR": 15.281
    

What is the standard for formatting currency values in JSON?

【讨论】:

【参考方案2】:

我认为一种解决方案是将数量乘以 100 作为 整数

$100 --> 10000 $1.5 --> 150 19.99 美元 --> 1999

(无舍入错误,安全存储在数据库中,除非您在货币兑换市场中使用它时需要更多小数)。

这样你就可以操纵你的数量(加法或乘法,..),然后再除以 100 来显示它。

【讨论】:

没错。如果您认为需要浮点数,您可能不了解缩放。对于金钱来说,这是一个独特的可怕想法!请记住,“过去”C 甚至没有浮点,这并不重要,因为 CPUs 无论如何也做不到。 这并不能解决问题,只是在显示数量时添加一些噪音 @deblocker 这会增加什么样的噪音?我认为这很好地满足了原始问题中提出的要求。它允许传递一个精确的值,然后客户端可以根据需要处理显示它。它还使处理国际化和本地化变得容易。这也是 Strip 在其 API 中处理货币的方式。 @ChrisBaldwin:因为 JSON 不区分整数和浮点数,就像它不区分货币和浮点数一样。所以说:“将它作为整数传递”对我来说简直是无稽之谈。指定子类型的唯一方法是在 JSON 模式中添加一个附加参数,例如:type: integer, value: 1000。但是这个属性的解释是专有的。 “将其作为整数传递”只是意味着像编写整数值一样编写它:只有数字,没有小数点或指数。这并不意味着您应该在 JSON 中将其声明为整数。【参考方案3】:

JSON 没有用于整数和浮点的不同类型 价值观。因此,JSON Schema 不能单独使用类型来区分 在整数和非整数之间。

因此,您可以尝试这样的方式。

var jsonObj = [
"amount": "$1234.46"
,
"amount": "$2234.56"
,
"amount": "$3234.66"
];

for (var i in jsonObj) 
  jsonObj[i].amount = '$'+Math.round(jsonObj[i].amount.substring(1,jsonObj[i].amount.length));


console.log(jsonObj);

希望,它会按照您的期望工作。谢谢

【讨论】:

【参考方案4】:

我认为没有“最佳实践”。

不过,我的建议是将它们编码为浮点数,这样您就不会混合显示美元的方式。例如,您可能希望避免通过

 "dollars": "1,000$" 
 "dollars": "1000.00$" 
 "dollars": "1000.00" 
 "dollars": "$1000.00" 

表示美元的更简单方法是使用浮点数。精度可以变化,这可能是一件好事

 "dollars": 1000.00 
 "dollars": 0.001231231 

注意0.00由于四舍五入而呈现为0.001的情况

 "dollars": 0.005 

【讨论】:

我不确定使用浮点数是不是最好的主意。一个系统上的 1.0f 可以在另一个系统上呈现为 0.9999999999f。 同意,但您可以将它们视为实数,直到您尝试以任何语言使用它们。一旦你将 JSON 解析成某种东西,你总是需要处理浮点错误。 @MajidLaissi:因为我对这个话题真的很感兴趣,请您提供一个可重现的 1.0f 呈现为 0.9999999999f 的示例? 想象一下让您的系统将 1/3 添加到 1/9,答案显然是 1,但在某些系统上它可能显示为 0.999999 或 1.0000001 而不是 1。home.wordpress.com/2013/07/31/float-and-double-13-23-0-99999999

以上是关于在 JSON 中传递美元金额的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将货币金额四舍五入到最接近的镍、四分之一、1 美元、5 美元等面额的最佳方法是啥?

在 ReactJs 中,从 redux 存储或从父级到子级将 props 传递给子组件的最佳实践是啥?

对于创建操作,使用表单数据,但在 Tortoise ORM 文档中他们使用 JSON,最佳实践是啥?

MVC 验证 - 使用服务层保持 DRY - 最佳实践是啥?

将变量从一个 HTML 页面传递到另一个页面的最佳实践是啥?

循环定时 jquery 函数的最佳实践是啥