swift - 使 Enum 符合 Codable 并映射到模型

标签 swift enums codable

我正在访问公共(public)交通 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 扩展,用于将某些类型转换为另一种类型。 float 例如..

如何在解码时自动将枚举映射到我的模型,以便我获得附加到它的枚举值(参见枚举),而不是字符串?我可以直接使枚举符合 Codable 吗?

最佳答案

我对此的建议是继续并使 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"
    }
}

关于swift - 使 Enum 符合 Codable 并映射到模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53090061/

相关文章:

swift - 编译器选择了错误的初始化程序

java - 在Java中如何编写代码来循环任意枚举?

java - 枚举多模式

ios - 带有泛型的Swift Codable,可保存响应中的通用数据

swift - 列表不符合 Encodable

ios - Swift ios 如何设置导航栏图像不拉伸(stretch)

swift - 将 Double 从核心数据返回到文本字段

java - 包含空格的枚举值

ios - 获取 api swift 可编码和模型数据中的位置

swift - 有效地包裹双