Search code examples
iosjsonswiftcodabledecodable

Decode Dynamic Types in Swift


I have an API response that is returning a list of objects that are sometimes different and I am having issues trying to decode the list properly. The list will have the object type as the key and then the actual object, it is custom objects types but to save time it looks like this below.

How can I write a custom decode function to decode this response properly?

{
    data: [
        {
            key: "word",
            object: "hello"
        },
        {
            key: "number",
            object: 15
        }
    ]
}

My code so far:

struct Reponse: Decodable {
    let data: [Objects]
}

struct Objects: Decodable {
    let key: String
    let object: ObjectType
}

enum ObjectType: Decodable {
    case word(String)
    case numbers(Int)
}

Solution

  • Here is a solution with an added enum for the key attribute that is used for determining how to decode the object attribute

    enum KeyDefinition: String, Decodable {
        case word, number
    }
    

    And the custom decoding

    struct Response: Decodable {
        let data: [DataObject]
    }
    
    struct DataObject: Decodable {
        let key: KeyDefinition
        let object: ObjectType
    
        enum CodingKeys: String, CodingKey {
            case key, object
        }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            key = try container.decode(KeyDefinition.self, forKey: .key)
            switch key {
            case .number:
                let number = try container.decode(Int.self, forKey: .object)
                object = ObjectType.numbers(number)
            case .word:
                let string = try container.decode(String.self, forKey: .object)
                object = ObjectType.word(string)
            }
        }
    }