Соответствие Enum к Codable и отображение на модель - PullRequest
0 голосов
/ 31 октября 2018

Я получаю доступ к API общественного транспорта и сопоставляю ответ с моделью, используя Codable и Alamofire 5.

В основном это работает, но API не нормализован правильно, то есть я получаю разные типы данных для одних и тех же свойств (линии шины могут быть либо Int, либо String и т. Д.)

Я пытаюсь отобразить свойство типа транспортных средств в перечисление, которое выглядит следующим образом:

enum VehiculeType {

    case bus
    case trolleybus
    case tram

    init?(rawValue: String) {
        switch rawValue {
        case "AB", "ABA", "ABAA":
            self = .bus
            break
        case "TBA", "TBAA":
            self = .trolleybus
        case "TW6", "TW7", "TW2":
            self = .tram
        default: return nil
        }
    }
}

А вот моя модель, которая до сих пор правильно декодирует.

struct Departure: Codable {

//    let lineCode: String
    let destination: String
    let waitingTime: Int
    let waitingMilliseconds: Int
    let reroute: String
//    let vehiculeType: VehiculeType?


    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        destination = try container.decode(String.self, forKey: .destination)
        waitingTime = try container.decode(Int.self, forKey: .waitingTime, transformFrom: String.self) ?? 0
        waitingMilliseconds = try container.decode(Int.self, forKey: .waitingMilliseconds)
        reroute = try container.decode(String.self, forKey: .reroute)
//        vehiculeType = try container.decodeIfPresent(String.self, forKey: .vehiculeType, transformFrom: String.self) // This does not work. Correct implementation needed here
    }
}

extension Departure {
    enum CodingKeys: String, CodingKey {
        case destination = "destination"
        case waitingTime = "attente"
        case waitingMilliseconds = "attenteMilli"
        case reroute = "deviation"
//      case vehiculeType
    }
}

Также у меня есть KeyedDecodingContainer расширение, реализованное для преобразования некоторых типов в другие. Поплавок например ..

Как я могу автоматически сопоставить enum с моей моделью, когда она декодируется, чтобы я прикреплял к ней значения enum (см. Enum) вместо Strings? Могу ли я подчинить enum непосредственно Codable?

1 Ответ

0 голосов
/ 31 октября 2018

Я бы порекомендовал сделать так, чтобы VehicleType можно было декодировать. Обратите внимание, что вы можете использовать Decodable вместо Codable, чтобы упростить задачу, и вам не нужно будет реализовывать логику кодирования, если вы никогда не собираетесь преобразовывать этот объект обратно.

Ваш окончательный код будет выглядеть примерно так:

enum DecodingError: Error {
case unknownVehiculeType
}

enum VehiculeType: Decodable {

    case bus
    case trolleybus
    case tram

    init(from decoder: Decoder) throws {
        let rawValue = try decoder.singleValueContainer().decode(String.self)
        switch rawValue {
        case "AB", "ABA", "ABAA":
            self = .bus
            break
        case "TBA", "TBAA":
            self = .trolleybus
        case "TW6", "TW7", "TW2":
            self = .tram
        default:
            throw DecodingError.unknownVehiculeType
        }
    }
}

struct Departure: Decodable {

    //    let lineCode: String
    let destination: String
    let waitingTime: Int
    let waitingMilliseconds: Int
    let reroute: String
    let vehiculeType: VehiculeType?


    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        destination = try container.decode(String.self, forKey: .destination)
        waitingTime = try container.decode(Int.self, forKey: .waitingTime, transformFrom: String.self) ?? 0
        waitingMilliseconds = try container.decode(Int.self, forKey: .waitingMilliseconds)
        reroute = try container.decode(String.self, forKey: .reroute)
        vehiculeType = try container.decodeIfPresent(VehiculeType.self, forKey: .vehiculeType)
    }
}

extension Departure {
    enum CodingKeys: String, CodingKey {
        case destination = "destination"
        case waitingTime = "attente"
        case waitingMilliseconds = "attenteMilli"
        case reroute = "deviation"
        case vehiculeType = "vehiculeType"
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...