hlovatt
(Howard Lovatt)
1
I think the following is correct:
public extension LosslessStringConvertible where Self: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode("\(self)")
}
}
public extension LosslessStringConvertible where Self: Decodable {
init(from decoder: Decoder) throws {
let stringRep = try decoder.singleValueContainer().decode(String.self)
self.init(stringRep)!
}
}
// Opt in.
extension Float80: Codable {}
// Test.
import Foundation
let f80 = Float80(3.142)
let encodedData = try JSONEncoder().encode(f80)
print(String(data: encodedData, encoding: .utf8)!)
let decodedF80 = try JSONDecoder().decode(Float80.self, from: encodedData)
print(decodedF80 == f80)
Unfortunately the encoding fails at runtime with the error:
Thread 1: Fatal error: Error raised at top level: Swift.EncodingError.invalidValue(3.141999999999999904, Swift.EncodingError.Context(codingPath: [], debugDescription: "Top-level Float80 encoded as string JSON fragment.", underlyingError: nil))
Is this a bug?
itaiferber
(Itai Ferber)
2
The issue is that JSONEncoder does not currently allow top-level fragments — you would be able to encode [f80] or {“...”: f80} but not f80 directly, unfortunately.
This is something we’d like to address at some point soon — please see Top-level \(T.self) encoded as number JSON fragment and associated threads/bugs (SR-6163) for more info.