The future of serialization & deserialization APIs

I don't totally agree that Codable is an effort to serialise a type to multiple formats. Ideally, looking at Codable without any custom codable functions, it is really an effort to serialise to and from a single format: key-value coded Swift structs.

The problem with Codable – and what I think you're getting at when you suggest we need JSONCodable/PlistCodable – is there's no sane custom implementation of init(from:) and encode(to:) without being archive-specific. These functions are generally a mashup of two different ideas:

  1. migration and versioning
  2. archive-specific choices like which fields to include and what order

But moreover, while you might make archive-specific choices, you don't always have archive-specific knowledge. Take for example, trying to decode a value from an archive that might include any common "property tree" value:

public init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    if container.decodeNil() {
        self = .null
    } else if let stringValue = try? container.decode(String.self) {
        self = .string(stringValue)
    } else if let intValue = try? container.decode(Int.self) {
        self = .integer(intValue)
    } else if let doubleValue = try? container.decode(Double.self) {
        self = .double(doubleValue)
    } else if let boolValue = try? container.decode(Bool.self) {
        self = .boolean(boolValue)
    } else if let array = try? container.decode([DatabaseLiteralValue].self) {
        self = .array(try JSONEncoder().encode(array))
    } else {
        self = .object(try JSONEncoder().encode(container.decode([String: DatabaseLiteralValue].self)))
    }
}

We have no lookahead. We can't peek to see if the next char is a double-quote, a digit or a bracket. Without overloading the Decoder to emit lookahead metadata as decodable types, you simply need to try each possibility, in turn, incurring the overhead and disruption of thrown errors.

I'd hope the visitor pattern here would be able to come back and say: I've already decoded the Bool type and just eliminate this need for archive-specific knowledge and ad-hoc parsing within the Decoding implementation.

10 Likes