yonaskolb / SwagGen

OpenAPI/Swagger 3.0 Parser and Swift code generator
MIT License
626 stars 146 forks source link

Floating point precision issues with JSONSerialization #204

Closed jrcmramos closed 4 years ago

jrcmramos commented 4 years ago

This issue happens during the (de)serialisation of JSON content while working with floating point types. When defining a number property in the OpenAPI spec, the same number will not be internalised and serialised to the same value using the default JSONEncoder and JSONDecoder. Here is an example:

import Cocoa

struct PayloadEx: Codable {
    let value: Double?

    enum CodingKeys: String, CodingKey {
        case value
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        value = try values.decodeIfPresent(.value)
    }
}

extension KeyedDecodingContainer {
    func decodeIfPresent<T>(_ key: KeyedDecodingContainer.Key) throws -> T? where T: Decodable {
        return try decodeIfPresent(T.self, forKey: key)
    }
}

let payload = """
{
  "value": 5.02
}
"""

let payloadData = payload.data(using: .utf8)

let decoder = JSONDecoder()
let model = try decoder.decode(PayloadEx.self, from: payloadData!)

print(model.value) // Optional(5.02)

let jsonEncoder = JSONEncoder()

print(String(decoding: try! jsonEncoder.encode(model), as: UTF8.self)) // {"value":5.0199999809265137}

This issue is related and better described in this bug report https://bugs.swift.org/browse/SR-7054?page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel . However this is not a problem related with the implementation of the framework, we will most likely have issues in case we are using CRUD API endpoints making use of number properties.

Our current solution implements a new Encoder class that (as described in one of the solutions of the above mentioned ticket) converts the Double to Decimal and then encodes it.

yonaskolb commented 4 years ago

This PR should help with adding your own Encoder https://github.com/yonaskolb/SwagGen/pull/203

yonaskolb commented 4 years ago

Closing this for now. Let me know @jrcmramos if that doesn't work