1

When working with decimals encoding a value of e.g 68.32 does not result in the same value when decoding it afterwards.

I'm using the suggestion from https://forums.swift.org/t/decimal-has-no-rounded/14200/12 to round the value before encoding it.

Might this be a bug in the JSONEncoder / JSONDecoder? Is there any reliable workaround?

Here is an example code:

import Foundation

let decimalValue: Decimal = 68.32 // 68.31999999999998976
let roundedDecimalValue = decimalValue.rounded(2, .plain) // 68.32

do {
    let data = try JSONEncoder().encode(roundedDecimalValue)
    let decodedDecimal = try JSONDecoder().decode(Decimal.self, from: data) // 68.31999999999999
    print(decodedDecimal)
} catch {}

extension Decimal {
    mutating func round(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) {
        var localCopy = self
        NSDecimalRound(&self, &localCopy, scale, roundingMode)
    }

    func rounded(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) -> Decimal {
        var result = Decimal()
        var localCopy = self // 68.31999999999998976
        NSDecimalRound(&result, &localCopy, scale, roundingMode)
        return result // 68.32
    }
}

Edit: I've ended up implementing a solution based on Swift: Decode imprecise decimal correctly

ProtocolGuy
  • 144
  • 8
  • I've found bug reports [this](https://bugs.swift.org/browse/SR-12244) and [this](https://bugs.swift.org/browse/SR-7054) that is exactly this problem. – Sweeper Jan 18 '22 at 13:42
  • 1
    Unfortunately this is a long outstanding bug in `(NS)Foundation`, which has leaked into `JSONEncoder`/`JSONDecoder`, since under the hood both use `JSONSerialization`, which itself contains the bug. [SR-7054](https://bugs.swift.org/browse/SR-7054) – Dávid Pásztor Jan 18 '22 at 13:43
  • Also observed here: https://stackoverflow.com/q/56805881/1187415. – Martin R Jan 18 '22 at 14:21
  • You need to encode it as Data or as a String https://stackoverflow.com/a/62997953/2303865. Make sure to make it a property of another structure – Leo Dabus Jan 18 '22 at 14:26
  • Found an answer with a solution that actually works for me: https://stackoverflow.com/questions/55131400/swift-decode-imprecise-decimal-correctly/55131900#55131900 – ProtocolGuy Jan 24 '22 at 12:56

0 Answers0