You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4中如何用标准Decodable解析Bool/Int类型的属性?

在Swift 4中用Decodable解析混合布尔/整数类型的属性

这种服务器返回属性类型不统一的情况确实挺头疼的——一会儿是布尔值true/false,一会儿又变成整数0/1,默认的Decodable肯定直接报错。不过咱们完全可以用Swift标准库的Codable协议自定义解码逻辑来搞定,不用装第三方库。

方案一:直接在Model类里自定义解码逻辑(推荐统一类型)

如果业务上希望把这个属性统一成布尔值(毕竟0和false、1和true语义一致),可以修改你的MyOffer类,重写init(from decoder: Decoder)方法来处理类型兼容:

final class MyOffer: Codable {
    var id = 0
    var pickupAsap: Bool? // 统一为布尔类型,更符合业务逻辑

    enum CodingKeys: String, CodingKey {
        case id
        case pickupAsap = "pickup_asap"
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 正常解析固定类型的id
        id = try container.decode(Int.self, forKey: .id)
        
        // 处理pickupAsap的类型兼容
        do {
            // 先尝试按布尔值解码(对应服务器返回true/false的情况)
            pickupAsap = try container.decode(Bool.self, forKey: .pickupAsap)
        } catch DecodingError.typeMismatch {
            // 类型不匹配时,说明返回的是整数,转成布尔值(0→false,非0→true)
            let intValue = try container.decode(Int.self, forKey: .pickupAsap)
            pickupAsap = intValue != 0
        } catch {
            // 其他解码错误直接抛出,保持默认的缺失处理逻辑
            throw error
        }
    }
}

方案二:通用的混合类型枚举(灵活复用)

如果你有多个属性都存在这种类型不统一的情况,可以写一个通用的BoolOrInt枚举,实现Decodable协议,这样可以把兼容逻辑复用起来:

// 定义一个能兼容布尔和整数的枚举
enum BoolOrInt: Decodable {
    case bool(Bool)
    case int(Int)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        // 先尝试解码布尔值,失败再试整数
        if let boolVal = try? container.decode(Bool.self) {
            self = .bool(boolVal)
        } else if let intVal = try? container.decode(Int.self) {
            self = .int(intVal)
        } else {
            // 既不是布尔也不是整数,抛出解码错误
            throw DecodingError.typeMismatch(
                BoolOrInt.self,
                DecodingError.Context(
                    codingPath: decoder.codingPath,
                    debugDescription: "Expected value to be either Bool or Int"
                )
            )
        }
    }

    // 方便快速获取布尔值
    var boolValue: Bool {
        switch self {
        case .bool(let val): return val
        case .int(let val): return val != 0
        }
    }

    // 方便快速获取整数值
    var intValue: Int {
        switch self {
        case .bool(let val): return val ? 1 : 0
        case .int(let val): return val
        }
    }
}

然后在MyOffer里直接用这个枚举类型:

final class MyOffer: Codable {
    var id = 0
    var pickupAsap: BoolOrInt? // 使用通用枚举类型

    enum CodingKeys: String, CodingKey {
        case id
        case pickupAsap = "pickup_asap"
    }
}

使用的时候就可以通过pickupAsap?.boolValue或者pickupAsap?.intValue轻松拿到统一格式的值,非常灵活。

小提示

如果业务上确实需要保留原始的类型(既可能是Bool也可能是Int),也可以把属性类型设为Any?,但后续使用时需要做类型判断,代码会繁琐很多,所以更推荐统一成单一类型,减少后续的类型处理成本。

内容的提问来源于stack exchange,提问作者Yurii Radchenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:30:35