Floating point precision issues with JSONSerialization
jrcmramos opened this issue · comments
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.
This PR should help with adding your own Encoder #203
Closing this for now. Let me know @jrcmramos if that doesn't work