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)
}
I get Fatal Error: "Expected to decode String but found a number instead."
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)
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
, store it intoDecimal
and thenround
it to a given number ofDecimal
digits. – ReisfieldJSONDecoder
usesNSJSONSerialization
internally, which decodes toDouble
. So even if you decode aDecimal
, it is first internally decoded to aDouble
and hence precision is lost. As Sulthan pointed out, there's a workaround, but there's no real solution due to this implementation issue. – Entomostracan