[swift-evolution] [Review] SE-0166: Swift Archival & Serialization
Tony Parker
anthony.parker at apple.com
Mon Apr 10 17:13:47 CDT 2017
Hi Rex,
> On Apr 10, 2017, at 12:48 PM, Rex Fenley via swift-evolution <swift-evolution at swift.org> wrote:
>
> Forgive me if I'm missing something, this is a very large proposal and a lot to parse through. I like how everything is designed as far as I can tell except I'm not sure from this proposal how one would compose multiple different types of Decoders against the same output type. For example, with Location we have.
>
> // Continuing examples from before; below is automatically generated by the compiler if no customization is needed.
> public struct Location : Codable {
> private enum CodingKeys : CodingKey {
> case latitude
> case longitude
> }
>
> public init(from decoder: Decoder) throws {
> let container = try decoder.container(keyedBy: CodingKeys.self)
> latitude = try container.decode(Double.self, forKey: .latitude)
> longitude = try container.decode(Double.self, forKey: .longitude)
> }
> }
>
> However, this initializer seems strictly tied to the `CodingKeys` set of coding keys. From what it appears, if this was used to decode from JSON the format would have to always be:
>
> {
> "latitude" : 20.0
> "longitude" : 20.0
> }
>
> I have a use case we're on my client we began the process of switching from one version of an API to another. In one version we had a payload similar to
>
> {
> "user" : {
> "uuid" : "uuid string..."
> "can_send_message" : true
> "can_delete_message" : false
> }
> }
>
> this would result in the following Codable (from "user") from what I'm following
>
> public struct User : Codable {
> private enum CodingKeys : CodingKey {
> case uuid
> case can_send_message
> case can_delete_message
> }
>
> public init(from decoder: Decoder) throws {
> let container = try decoder.container(keyedBy: CodingKeys.self)
> uuid = try container.decode(Double.self, forKey: .uuid)
> canSendMessage = try container.decode(Bool.self, forKey: .can_send_message)
> canDeleteMessage = try container.decode(Bool.self, forKey: .can_delete_message)
> }
> }
>
> when we began switching over to the new api the payload was returned as
>
> {
> user {
> "uuid" : "uuid string..."
> "permissions" : {
> "can_send_message" : true
> "can_delete_message" : false
> }
> }
> }
>
> Here with "permissions" we have a new internal container with a separate set of coding keys. Issue is in my use case I still need to maintain a way to decode the old version simultaneously; we guard all new changes behind feature flags in case something goes awry and we need to roll back our changes.
>
> How would one go about expressing this new Decoding and the previous Decoding simultaneously on the same User type?
You would fall out of the automatically-generated scenario here, but this use case is exactly what the ‘container’ API is for. You can create a container with a new set of keys, then decode from it.
Another approach would be to create a nested type that conforms with Codable which represents the “permissions” as a type of its own.
- Tony
>
>
> --
> Rex Fenley | IOS DEVELOPER
>
>
> Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170410/3d2d0c18/attachment.html>
More information about the swift-evolution
mailing list