The future of serialization & deserialization APIs

Great to see this progress so early, thank for sharing it! I have a couple of questions about somewhat niche Codable patterns, which I wonder if they could be easily supported in this new library. If the answer is "not really" I don't think that's a problem, as these really are slightly oddball, but I would be personally delighted if they turn out to be easier in this paradigm than with Codable.

  1. Let's call this one "coding mixins". This is where an API documents something like "all objects served via this API have the metadata properties @@type, @@url, @@last_changed_datetime, and @@id." With Codable and knowing I was decoding JSON I could do a quite dubious generic-composition dance to put the decoding rules for these properties in just one place. It seems like that wouldn't be possible under this new proposal because the container controls the order keys are delivered in. The best alternative I saw myself was a protocol requiring that all my API-model types have these properties, but I think I would still need to manually annotate each model type with the coding details (the non-standard keys and the encoding of the date field). Is there some better alternative (even if only sketchy, or in prior art elsewhere) that I'm missing?
  2. My other niche interest is format-shifting. Suppose I want to reuse the same model but encode/decode it into multiple formats (speculative use cases: json/plist, with the different date representations implied; different API versions that change the encoding spec but preserve the semantics as in "we now use camelCase for all properties"; a rich representation for snapshot-testing and a stripped representation for public API traffic). Since the serialisation control lives as macros (@CodingDefault and @CodingKey and so on, whatever their eventual spelling turns out to be) on the model-type's properties, it seems like I would need a separate model type for each serialisation format. (This is possible, but keeping those types in sync is harder than I would prefer if they include optionals or properties with default values.) But I'm wondering about the possibility to decouple two distinct types: (a) the Visitor.DecodedValue type which is produced by decoding, but also (b) a "coding specification" type which provides the keys, formats, defaults, etc. In the normal case these are the same type, but the format-shifting use case would be helped if it were possible to separate them (even if that meant forgoing some of the concise representation), e.g.
@JSONCodableExplicit(decodedValue=BlogPost.self)
struct BlogPostJSONCoding {
    let title: String // the macro would complain if these properties don't match BlogPost
    let subtitle: String?
    @CodingKey("date_published") @CodingFormat(.iso8601)
    let publishDate: Date
    // etc
}

@PListCodableExplicit(decodedValue=BlogPost.self)
struct BlogPostJSONCoding { ... }

Or alternatively, perhaps an optional specifier in the @CodingXYZ family of macros allowing to stack multiple copies to be used by different en/decoders:

@CodingKey("date_published", for: .json)
@CodingKey("datePublished", for: .thatAPIVersion2) // I would need to be able to name my own refinements for ad-hoc cases like this
@CodingFormat(.iso8601, for: .json)
@CodingFormat(.native, for: .plist)
let publishDate: Date
3 Likes