Swift 4 JSON Codable – value returned is sometimes an object, others an array

You might encapsulate the ambiguity of the result using an Enum with Associated Values (String and Array in this case), for example:

enum MetadataType: Codable {
    case array([String])
    case string(String)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            self = try .array(container.decode(Array.self))
        } catch DecodingError.typeMismatch {
            do {
                self = try .string(container.decode(String.self))
            } catch DecodingError.typeMismatch {
                throw DecodingError.typeMismatch(MetadataType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Encoded payload not of an expected type"))
            }
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .array(let array):
            try container.encode(array)
        case .string(let string):
            try container.encode(string)
        }
    }
}

struct Hotel: Codable {
    let firstFloor: Room

    struct Room: Codable {
        var room: MetadataType
    }
}

Leave a Comment