Codable decoding with Metatype

Hi,

I try implement decoding to different object types based on (some external) type information.
The following code fails to compile with
error: cannot invoke 'decode' with an argument list of type '(TestProtocol.Type, from: Data)'
How can I get that code to compile?

    import Foundation

    protocol TestProtocol : Codable {
        func hello() -> String
    }

    class TestObject : TestProtocol {
        var stringVar = "World"
        func hello() -> String { return stringVar }
    }

    let clazz : TestProtocol.Type = TestObject.self
    let codableClazz : Codable.Type = clazz
    print( "\(clazz) \(codableClazz)" )

    let decoder = JSONDecoder()
    let data = Data()  // should be real data... 

    try? decoder.decode( codableClazz, from: data)

You have to pass concrete type to decode. Protocols can't conform to protocols.

Sigh By using concrete types the code works but I loose compiler support for the Codable code generation as soon as I inherit from the 'Codable' base class :

    import Foundation

    protocol TestProtocol : Codable {
        func hello() -> String
    }

    class TestObjectBase : TestProtocol {
        func hello() -> String { return "" }
    }

    class TestObject : TestObjectBase {
        var s = "Initial Value"
        override func hello() -> String { return s }

        // Necessary only if derived from a "Codable" base class: 
        enum CodingKeys: String, CodingKey{ case s }
        required init(from decoder: Decoder) throws {
            try super.init(from: decoder )
            let container = try decoder.container(keyedBy: CodingKeys.self)
            s = try container.decode(String.self, forKey: .s )
        }
    }

    let clazz : TestObjectBase.Type = TestObject.self
    let codableClazz : Codable.Type = clazz
    print( "\(clazz) \(codableClazz)" )

    let decoder = JSONDecoder()
    let data = "{ \"s\": \"Sample\" }".data(using: .utf8 )

    let objFromClazz = try? decoder.decode( clazz, from: data! )
    print( "Using clazz: \(objFromClazz?.hello() ?? "<nil>")" )

    let objFromType = try? decoder.decode( TestObject.self, from: data! )
    print( "Using type: \(objFromType?.hello() ?? "<nil>")" )

For me it compiles without need to define CodingKeys and init(decoder:) explicitly. Could you share some more info about error you are getting?

Terms of Service

Privacy Policy

Cookie Policy