Search code examples
swiftios13codable

Parsing Decimal from JSON presented as string


With Xcode 10.2 and iOS 12.x we were able to extract Decimal from json string. With Xcode 11.1 and iOS 13.1 it is throwing exception

Expected to decode Double but found a string/data instead.

class MyClass : Codable {

     var decimal: Decimal?
 }

then trying to parse it

let json = "{\"decimal\":\"0.007\"}"
let data = json.data(using: .utf8)
let decoder = JSONDecoder()
decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "s1", negativeInfinity: "s2", nan: "s3")
 do {
   let t = try decoder.decode(MyClass.self, from: data!)
 } catch {
   print(error)
 }

If I change json string as

let json = "{\"decimal\":0.007}"

It works, but then again we are losing precision. Any ideas?


Solution

  • struct Root: Codable {
        let decimal: Decimal
    }
    

    extension Root {
        public init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            decimal = try Decimal(string: container.decode(String.self, forKey: .decimal)) ?? .zero
        }
    }
    

    let json = #"{"decimal":"0.007"}"# 
    do {
        let root = try JSONDecoder().decode(Root.self, from: .init(json.utf8))
        print(root)
    } catch {
        print(error)
    }
    

    This will print

    Root(decimal: 0.007)