# Decodable, protocol conformance, and generics: how to "dumb down" a conforming type to call the right implementation

**URL:** <https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851>\
**Category:** Using Swift\
**Tags:** generics, codable, protocols\
**Created:** [October 15, 2019, 8:08pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851 "2019-10-15T20:08:40Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrlegowatch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mrlegowatch/32/5126_2.png) [@mrlegowatch](https://forums.swift.org/u/mrlegowatch)\
**Post date:** [October 15, 2019, 8:08pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/1 "2019-10-15T20:08:40Z")

</div>

I am working on migrating a data storage library from Objective-C to Swift, with Codable, and I'm running into a problem with how to support migration from "anonymous" (embedding) types to Codable. To support the migration, First, I need to migrate a little bit of pre-existing generic metadata when decoding each old type. Then, what I would like to do is make that intermediate step invisible to the client, so that init(from:) does not need to be implemented by hand.

The first part I can do, if I implement a custom method on the KeyedDecodingContainer, similar to this:

```
public extension KeyedDecodingContainer { 
    func decodeAnonymousIfPresent<T: Codable>( _ codable: T.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> T? {
    if let decoded = try ? decodeIfPresent(T.self, forKey: key) {
        return decoded
    } else if let anonymousObject = try ? decodeIfPresent(__AnonymousObjC.self, forKey: key) {
        // code to migrate metadata from the old type to the new one snipped
    }
}

```

And in the caller, I can use this in an init(from:) method:

```
required init (from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self )
    let address = try container.decodeAnonymousIfPresent(SwiftyAddress.self , forKey: .address)
    /// etc.
}

```

If the old data is present, it will migrate to the new object (via generic metadata shenanigans), and if the new data is present, the new object will initialize directly.

The trouble is, I have a lot of data types, and I'd rather not implement `init(from:)` methods for the ones that can get away without one, just for the sake of migration.

The current path I am on, is to introduce a new, empty protocol to support the migration, for example:

`public protocol Migratable: Codable { }`

Then, instead of implementing `init(from:)`, just declare conformance for each type, like this:

`extension SwiftyAddress: Migratable { }`

Then, I'd want to modify the KeyedDecodingContainer methods to map directly to the decode implementations, like this:

```
public extension KeyedDecodingContainer { 
    func decodeIfPresent<T: Migratable>( _ migratable: T.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> T? {
    if let decoded = try ? decodeIfPresent(T.self, forKey: key) {
        return decoded
    } else if let anonymousObject = try ? decodeIfPresent(__AnonymousObjC.self, forKey: key) {
    // code to migrate metadata from the old type to the new one snipped
    }
}

```

What I need for this to work, however, is to fix the line `if let decoded = try ? decodeIfPresent(T. self , forKey: key)` to decode a `T: Codable`, not the `T: Migratable`, so that it calls the Codable decode method. (As written, it goes into infinite recursion.) Is such a thing possible?

If anyone has suggestions on how to continue down this path, or other alternative paths to explore, please let me know. Thanks in advance for your help!

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [October 15, 2019, 8:38pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/2 "2019-10-15T20:38:17Z")

</div>

You probably don't need new function on `KeyedDecodingContainer`. Synthesizer won't know about it so you won't be able to utilize default synthesis. It'd be easier to "wrap" every variable that support migration with type that handles fallback. Property wrapper should be a good fit.

```swift
@propertyWrapper
struct Migratable<Value: Decodable>: Decodable {
    var wrappedValue: Value
    
    init(from decoder: Decoder) throws {
        if let decoded = try? Value(from: decoder) {
            wrappedValue = decoded
        } else {
            // Setup from __AnonymousObjC here
            throw NSError()
        }
    }
}

extension Migratable: Encodable where Value: Encodable {
    func encode(to encoder: Encoder) throws {
        try wrappedValue.encode(to: encoder)
    }
}

```

So you can do

```swift
struct Test: Codable {
    @Migratable var value: Int
}

let data = #"{"value": 77}"#.data(using: .utf8)!
let decoder = JSONDecoder()
let encoder = JSONEncoder()

// Don't wrap top-level. Test(value: 77)
let test = try decoder.decode(Test.self, from: data)
// Wrap top-level as well. Test(value: 77)
let wrappedTest = try decoder.decode(Migratable<Test>.self, from: data).wrappedValue

try String(data: encoder.encode(test), encoding: .ascii) // #"{"value":77}"#

```

One problem would be if you want to have synthesizer uses `decodeIfPresent`, which is not something property wrapper supported (see discussion [here](https://forums.swift.org/t/using-property-wrappers-with-codable/29804/4)). In which case, you need to manually implement `init(from:)`.

---

<div class="post-metadata">

**Author:** ![mrlegowatch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mrlegowatch/32/5126_2.png) [@mrlegowatch](https://forums.swift.org/u/mrlegowatch)\
**Post date:** [October 16, 2019, 12:17pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/3 "2019-10-16T12:17:20Z")

</div>

Thanks for this suggestion for another path to explore, this is huge!

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [October 16, 2019, 1:44pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/4 "2019-10-16T13:44:40Z")

</div>

To further note, the details of property wrapper is described in [SE-0258](https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md), which is [accepted with modification](https://forums.swift.org/t/accepted-with-modification-se-0258-property-wrappers/26828).

It also support certain initialization syntax such as.

```swift
@Migratable(arg2: value2, arg3: value3) var foo: Int = 3
// Equivalent to
// var _foo = Migratable(wrappedValue: 3, arg2: value2, arg3: value3)

@Migratable var foo: Bar = Bar(...)
// var _foo = Migratable(wrappedValue: Bar(...))

```

So if you want any of that, you can customarily add `init`.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 16, 2019, 4:26pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/5 "2019-10-16T16:26:52Z")

</div>

@mrlegowatch I'm putting the finishing touches on [CodableWrappers](https://github.com/GottaGetSwifty/CodableWrappers) which makes this a bit simpler to implement.

```swift
public struct MigratingDecoder<T: Decodable>: StaticDecoder {

    public static func decode(from decoder: Decoder) throws -> T {
        if let decoded = try? T(from: decoder) {
            return decoded
        } else {
            // Setup from __AnonymousObjC here
            throw NSError()
        }
    }
}

struct MyStruct: Codable {
    // Set up like this, you will only override the Decoding and use the default Encoding
    @CustomDecoding<MigratingDecoder> var value: Int
}

```

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [October 16, 2019, 7:03pm UTC](https://forums.swift.org/t/decodable-protocol-conformance-and-generics-how-to-dumb-down-a-conforming-type-to-call-the-right-implementation/29851/6 "2019-10-16T19:03:10Z")

</div>

I'll answer the original question, since it's occasionally a useful pattern: the only way to do this in current Swift is to use a separate function with fewer constraints on the generic parameter:

```swift
public extension KeyedDecodingContainer { 
    private func decodeIfPresentDefault<T: Codable>( _ codable: T.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> T? {
        return try decodeIfPresent(codable, forKey: key)
    }

    func decodeIfPresent<T: Migratable>( _ migratable: T.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> T? {
        if let decoded = try decodeIfPresentDefault(T.self, forKey: key) {
            return decoded
        } else if let anonymousObject = try decodeIfPresentDefault(__AnonymousObjC.self, forKey: key) {
        // code to migrate metadata from the old type to the new one snipped
        }
    }
}

```

(That function doesn't have to live on the same extension either, but that seemed most convenient here.)
