gpt4 book ai didi

json - 使用 JSONSerialization 序列化货币时指定小数位数

转载 作者:搜寻专家 更新时间:2023-10-31 22:01:30 25 4
gpt4 key购买 nike

NumberFormatter 使得在屏幕上显示值时格式化货币非常容易:

let decimal = Decimal(25.99)
let decimalNumberFormatter = NumberFormatter()
decimalNumberFormatter.numberStyle = .currencyAccounting
let output = decimalNumberFormatter.string(for: decimal)
// output = "$25.99"

以上代码适用于任何 DecimalDouble 值。小数位数始终与所使用的区域设置相匹配。

将浮点货币值序列化为 JSON 并不是那么简单。

具有以下序列化方法(注意强制解包):

func serialize(prices: Any...) {
let data = try! JSONSerialization.data(withJSONObject: ["value": prices], options: [])
let string = String(data: data, encoding: .utf8)!
print(string)
}

然后我们可以用不同的值和类型调用它。 DoubleDecimalNSDecimalNumber(应该从 Swift 的 Decimal 桥接而来)无法正确呈现某些值例。

serialize(prices: 125.99, 16.42, 88.56, 88.57, 0.1 + 0.2)
// {"value":[125.99,16.42,88.56,88.56999999999999,0.3]}

serialize(prices: Decimal(125.99), Decimal(16.42), Decimal(88.56), Decimal(88.57), Decimal(0.1) + Decimal(0.2))
// {"value":[125.98999999999997952,16.420000000000004096,88.56,88.57,0.3]}

serialize(prices: NSDecimalNumber(value: 125.99), NSDecimalNumber(value: 16.42), NSDecimalNumber(value: 88.56), NSDecimalNumber(value: 88.57), NSDecimalNumber(value: 0.1).adding(NSDecimalNumber(value: 0.2)))
// {"value":[125.98999999999997952,16.420000000000004096,88.56,88.57,0.3]}

我不打算将数字序列化为货币(不需要货币符号,整数 (5) 或单个小数位 (0.3) 都可以)。但是,我正在寻找一种解决方案,其中序列化输出包含的小数位数不超过给定货币允许的小数位数(区域设置)。

也就是说,在将浮点值序列化为 JSON 时,有什么方法可以限制或指定要使用的小数位数吗?

更新#1:使用更多数据类型进行测试,令人惊讶的是,FloatFloat32 似乎都适用于两位小数的货币。 Float64 失败为 Double(可能它们是同一类型的别名)。

serialize(prices: Float(125.99), Float(16.42), Float(88.56), Float(88.57), Float(0.1) + Float(0.2))
// {"value":[125.99,16.42,88.56,88.57,0.3]}

serialize(prices: Float32(125.99), Float32(16.42), Float32(88.56), Float32(88.57), Float32(0.1) + Float32(0.2))
// {"value":[125.99,16.42,88.56,88.57,0.3]}

serialize(prices: Float64(125.99), Float64(16.42), Float64(88.56), Float64(88.57), Float64(0.1) + Float64(0.2))
// {"value":[125.99,16.42,88.56,88.56999999999999,0.3]}

不过,很难知道它们是否在所有情况下都能正常工作。 Float80 无法序列化并出现 _NSJSONWriter 异常。

最佳答案

在对此事进行了一些研究之后,一位同事发现使用 NSDecimalNumberHandler 舍入指定行为的值可以解决 JSON 序列化问题。

fileprivate let currencyBehavior = NSDecimalNumberHandler(roundingMode: .bankers, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)

extension Decimal {
var roundedCurrency: Decimal {
return (self as NSDecimalNumber).rounding(accordingToBehavior: currencyBehavior) as Decimal
}
}

按照帖子中的示例代码,我们得到了所需的输出:

serialize(prices: Decimal(125.99).roundedCurrency, Decimal(16.42).roundedCurrency, Decimal(88.56).roundedCurrency, Decimal(88.57).roundedCurrency, (Decimal(0.1) + Decimal(0.2)).roundedCurrency)
// {"value":[125.99,16.42,88.56,88.57,0.3]}

有效!对 10000 个值(从 0.0 到 99.99)进行了测试,没有发现任何问题。

如果需要,可以将比例调整为当前语言环境的小数位数:

var currencyFormatter = NumberFormatter()
currencyFormatter.numberStyle = .currencyAccounting
let scale = currencyFormatter.maximumFractionDigits
// scale == 2

关于json - 使用 JSONSerialization 序列化货币时指定小数位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45420375/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com