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)
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>")" )