swiftgenericsprotocolsdecodable

Decoding a Swift type which is only conditionally `Codable`


I have a Swift class that may or may not be Codable. When it is Codable, I would like to be able to load it from file. Here is a bare bones example...

protocol P {
    func load()
}

final class A<T>: P {
    func load() {
        if T.self is Codable.Type {
            let decoded = try JSONDecoder().decode(Self.self, from: Data())
        }
    }
}

extension A: Codable where T: Codable {}

I get an error that T is not Codable and the JSONDecoder requires it. It makes sense, because even though I do a run time check, the call to decode does not constrain T to be Codable.

I've tried a bunch of variations, like adding extensions with a where clause, but I'm yet to find the definitive answer.

Anyone know how to approach this?


Solution

  • import Cocoa
    
    protocol P {
        func load(from data: Data)
    }
    
    extension P {
        func load(from data: Data) {
            // print or something
            Swift.print("P.load")
        }
    }
    
    final class A<T>: P {
    }
    
    extension A: Codable where T: Codable {
        func load(from data: Data) {
            Swift.print("A.load where T Codable")
            let decoded = try! JSONDecoder().decode(Self.self, from: data)
        }
    }
    
    extension A {
        func load(from data: Data) {
            Swift.print("A.load")
        }
    }
    
    
    let four = 4
    let encoded = try JSONEncoder().encode(four)
    A<Int>().load(from: encoded)
    
    

    This worked for me in a playground. If overloading isn't working for you, then there is something like throws interacting with the compiler/runtime's choice of implementation.