Swift 4 - Codable - How to allow varying object types for a key when decoding

1k views Asked by At

I have a Swift app which I am in the process of converting over to use the Codable protocol (instead of EVReflection, which changed so much that I could no longer make it work). When transacting with the app server, my code generates an object of class "ServerResponse", which contains a number of variables - one of which is "responseObject" - which can be any number of different objects from a user, to a message, or others. Because Codable doesn't use "decodeIfPresent" by default, I was getting errors during certain transactions, and had to override init(from decoder: Decoder) to prevent this. Now I am left with the challenge of figuring out how to either leave the raw JSON string intact for decoding into the correct object type later by the calling method, or some other similar fix. Bottom line: I need responseObject to be flexible and allow any type of object that my server chooses to send.

If anyone has any suggestions, I'd be grateful. I'll be happy to share code if that will help, but I didn't think it would be since this question is mostly conceptual in nature.

1

There are 1 answers

0
Aks On

You can do something similar to this:-

struct CustomAttribute: Codable {
var attributeCode: String?
var intValue: Int?
var stringValue: String?
var stringArrayValue: [String]?

enum CodingKeys: String, CodingKey {

    case attributeCode = "attribute_code"
    case intValue = "value"
    case stringValue
    case stringArrayValue
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)

    attributeCode = try values.decode(String.self, forKey: .attributeCode)
    if let string = try? values.decode(String.self, forKey: .intValue) {
        stringValue = string
    } else if let int = try? values.decode(Int.self, forKey: .intValue) {
        intValue = int
    } else if let intArray = try? values.decode([String].self, forKey: .intValue) {
        stringArrayValue = intArray
    }
}

}

Here value can be of three types and I manually identify which type it is.