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

Swift Codable解码报错:数字2.87无法在Swift中表示的解决方法

解决Double解码"Number 2.87 is not representable in Swift"问题

方案1:改用Decimal类型存储并自定义解码

部分十进制小数无法用Double精确表示(比如2.87的二进制浮点数是近似值),改用Decimal类型能从根源避免这类问题,同时兼容JSON返回的数字格式。修改结构体并实现自定义解码逻辑:

struct CustomerEntries: Codable {
    var date: String
    var customer_rate: Decimal
    var percentage: Double
    
    enum CodingKeys: String, CodingKey {
        case date
        case customer_rate = "customer-rate"
        case percentage = "percentage-change"
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decode(String.self, forKey: .date)
        percentage = try container.decode(Double.self, forKey: .percentage)
        
        // 兼容数字和字符串两种格式的解码
        if let number = try? container.decode(Double.self, forKey: .customer_rate) {
            customer_rate = Decimal(number)
        } else if let stringValue = try? container.decode(String.self, forKey: .customer_rate) {
            guard let decimalValue = Decimal(string: stringValue) else {
                throw DecodingError.dataCorruptedError(forKey: .customer_rate, in: container, debugDescription: "无法将值转换为Decimal类型")
            }
            customer_rate = decimalValue
        } else {
            throw DecodingError.typeMismatch(Decimal.self, DecodingError.Context(codingPath: [.customer_rate], debugDescription: "不支持的数值类型"))
        }
    }
}

方案2:自定义Double解码扩展(坚持用Double时可选)

如果必须保留Double类型,可以扩展解码容器,添加兼容逻辑:

extension KeyedDecodingContainer {
    func decodeSafeDouble(forKey key: Key) throws -> Double {
        // 先尝试直接解码Double
        if let value = try? decode(Double.self, forKey: key) {
            return value
        }
        // 失败则转成字符串再解析
        let stringValue = try decode(String.self, forKey: key)
        guard let doubleValue = Double(stringValue) else {
            throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "无法将字符串\(stringValue)转换为Double")
        }
        return doubleValue
    }
}

之后在结构体的自定义解码中调用这个方法:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    date = try container.decode(String.self, forKey: .date)
    percentage = try container.decode(Double.self, forKey: .percentage)
    customer_rate = try container.decodeSafeDouble(forKey: .customer_rate)
}

问题本质说明

报错的核心原因是:JSON中的2.87是十进制精确值,但二进制浮点数Double只能精确表示2的幂次分数,无法精准存储2.87,导致系统判定该数值无法被Double表示而解码失败。Decimal类型专为十进制数值设计,能完美适配这类场景,尤其适合利率、金额等对精度敏感的数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:27:06