title: Polymorphically decode a sub-object of a KeyedDecodingContainer in Swift
body: <p>The following code attempts to create a <code>Codable</code> type <code>AnyBase</code> that would allow you to encode and decode various subclasses of <code>Base</code>. As written, in fails, because it tries to lookup the type objects by a string code, using <code>getTypeFromCode</code>. But if you use the commented-out part instead with hard-coded types, it prints "Sub1", as desired.</p>
  
  <p>Is there a way to adjust this to use something like <code>getTypeFromCode</code> and eliminate the hard-coded types from <code>init</code>?</p>
  
  <pre><code>class Base: Codable {
      var foo: Int = 1
      var codingTypeKey: String { fatalError("abstract") }
  }
  
  class Sub1: Base {
      var sub1Prop: Int = 2
      override var codingTypeKey: String { "sub1" }
      enum CodingKeys: CodingKey {
          case sub1Prop
      }
      override init() {
          super.init()
      }
      required init(from decoder: Decoder) throws {
          let c = try decoder.container(keyedBy: CodingKeys.self)
          sub1Prop = try c.decode(Int.self, forKey: .sub1Prop)
          try super.init(from: decoder)
      }
      override func encode(to encoder: Encoder) throws {
          var c = encoder.container(keyedBy: CodingKeys.self)
          try c.encode(sub1Prop, forKey: .sub1Prop)
          try super.encode(to: encoder)
      }
  }
  class Sub2: Base {
      var sub2Prop: Int = 2
      override var codingTypeKey: String { "sub2" }
  }
  
  func getTypeFromCode(_ typeCode: String) -&gt; Base.Type {
      if typeCode == "sub1" { return Sub1.self }
      else if typeCode == "sub2" { return Sub2.self }
      else { fatalError("bad type code") }
  }
  
  class AnyBase: Codable {
      let base: Base
      init(_ b: Base) { base = b }
      required init(from decoder: Decoder) throws {
          let c = try decoder.container(keyedBy: CodingKeys.self)
          let typeCode = try c.decode(String.self, forKey: .type)
  
          /*if typeCode == "sub1" {
              self.base = try c.decode(Sub1.self, forKey: .base)
          } else if typeCode == "sub2" {
              self.base = try c.decode(Sub2.self, forKey: .base)
          } else {
              fatalError("bad type code")
          }*/
  
          let typeObj = getTypeFromCode(typeCode)
          self.base = try c.decode(typeObj, forKey: .base)
      }
      func encode(to encoder: Encoder) throws {
          var c = encoder.container(keyedBy: CodingKeys.self)
          try c.encode(base.codingTypeKey, forKey: .type)
          try c.encode(base, forKey: .base)
      }
  
      enum CodingKeys: CodingKey {
          case base, type
      }
  }
  
  // To to round-trip encode/decode and get the right object back...
  let enc = JSONEncoder()
  let dec = JSONDecoder()
  let sub = Sub1()
  let any = AnyBase(sub)
  let data = try! enc.encode(any)
  let str = String(data:data, encoding:.utf8)!
  print(str)
  let any2 = try! dec.decode(AnyBase.self, from: data)
  print(type(of:any2.base))
  </code></pre>