Codable supports this, actually. CodingKey doesn't need to be an enum, it can be a struct. Then in your init(from:), you can loop over allKeys to read out your keys. For known keys, you can define static properties.
struct WhateverObject: Codable {
var myProperty: String // properties...
struct CodingKeys: CodingKey, Hashable {
var stringValue: String
static let myProperty = CodingKeys(stringValue: "myProperty")
init(stringValue: String) {
self.stringValue = stringValue
}
// Unused, only for int-backed Codables.
var intValue: Int? { return nil }
init?(intValue: Int) { return nil }
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
myProperty = container.decode(String.self, forKey: .myProperty)
let dynamicKeys = container.allKeys
for key in dynamicKeys {
// do whatever you want to do with the keys.
}
}
}