Swift:正确解码不精确的小数 [英] Swift: Decode imprecise decimal correctly
问题描述
I need to decode (Decodable
protocol) an imprecise decimal value correctly, from this question I understand how to properly handle the Decimal instantiation, but how can I do this when decoding?
如果尝试将任何数字初始化为字符串
If trying to init any number as a String
if let value = try! container.decode(String.self, forKey: .d) {
self.taxAmount = Decimal(string: value)
}
我得到Fatal Error: "Expected to decode String but found a number instead."
如果尝试将130.43初始化为小数
And if try to init 130.43 as a Decimal
if let value = try! container.decode(Decimal.self, forKey: .d) {
//value.description is 130.43000000000002048
self.d = Decimal(string: value.description)
//making subtotal to be also 130.43000000000002048 and not 130.43
}
解码时有什么方法可以使用其中一个构造函数吗?
Is there any way to use either of this constructors when decoding?
-
NSDecimalNumber(string: "1.66")
-
NSDecimalNumber(value: 166).dividing(by: 100)
-
Decimal(166)/Decimal(100)
-
Decimal(sign: .plus, exponent: -2, significand: 166)
NSDecimalNumber(string: "1.66")
NSDecimalNumber(value: 166).dividing(by: 100)
Decimal(166)/Decimal(100)
Decimal(sign: .plus, exponent: -2, significand: 166)
这是我从外部服务收到的JSON的简化版本:
Here is a simplified version of the JSON I receive from the external service:
{
"priceAfterTax": 150.00,
"priceBeforeTax": 130.43,
"tax": 15.00,
"taxAmount": 19.57
}
注意:我无法更改接收到的要解码的内容,我只能使用十进制数字.
Note: I can't change what is being received to be decoded, I'm stuck working with decimal numbers.
推荐答案
您可以实现自己的解码方法,并以最多两个小数位数的形式设置double格式,然后使用该字符串初始化您的十进制属性:
You can implement your own decoding method and format your double with maximum two fraction digits and use the string to initialize your decimal properties:
struct Root: Codable {
let priceAfterTax, priceBeforeTax, tax, taxAmount: Decimal
}
extension Root {
public init(from decoder: Decoder) throws {
var container = try decoder.container(keyedBy: CodingKeys.self)
let priceAfterTaxDouble = try container.decode(Double.self, forKey: .priceAfterTax)
priceAfterTax = Decimal(string: Formatter.decimal.string(for: priceAfterTaxDouble)!) ?? 0
let priceBeforeTaxDouble = try container.decode(Double.self, forKey: .priceBeforeTax)
priceBeforeTax = Decimal(string: Formatter.decimal.string(for: priceBeforeTaxDouble)!) ?? 0
let taxDouble = try container.decode(Double.self, forKey: .tax)
tax = Decimal(string: Formatter.decimal.string(for: taxDouble)!) ?? 0
let taxAmountDouble = try container.decode(Double.self, forKey: .taxAmount)
taxAmount = Decimal(string: Formatter.decimal.string(for: taxAmountDouble)!) ?? 0
}
}
extension Formatter {
static let decimal: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.decimalSeparator = "."
formatter.maximumFractionDigits = 2
return formatter
}()
}
let data = Data("""
{
"priceAfterTax": 150.00,
"priceBeforeTax": 130.43,
"tax": 15.00,
"taxAmount": 19.57
}
""".utf8)
let decodedObj = try! JSONDecoder().decode(Root.self, from: data)
decodedObj.priceAfterTax // 150.00
decodedObj.priceBeforeTax // 130.43
decodedObj.tax // 15.00
decodedObj.taxAmount // 19.57
这篇关于Swift:正确解码不精确的小数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!