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
相关产品推荐
相关产品推荐

