Hi Rex,

> On Apr 10, 2017, at 12:48 PM, Rex Fenley via swift-evolution 
> <[email protected]> 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
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to