Swift如何将Django返回的字符串格式decimal值解码为Double
解决方案
报错原因是Swift默认Decodable实现仅支持将JSON数字类型解析为Double,无法自动处理后端返回的字符串格式数值。最适合大量结构体复用的方案是使用属性包装器,只需一次定义,所有需要支持字符串转Double的属性加一行注解即可生效。
步骤1:定义可复用的属性包装器
@propertyWrapper struct StringToDouble: Codable { var wrappedValue: Double? init(wrappedValue: Double? = nil) { self.wrappedValue = wrappedValue } init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // 兼容直接返回数字的场景 if let doubleVal = try? container.decode(Double.self) { wrappedValue = doubleVal return } // 处理字符串格式的数值 if let stringVal = try? container.decode(String.self) { wrappedValue = Double(stringVal) return } // 处理null值 if container.decodeNil() { wrappedValue = nil return } // 异常场景可根据需求调整为抛出错误,默认置为nil wrappedValue = nil } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() guard let value = wrappedValue else { try container.encodeNil() return } // 若需要编码为字符串传给后端,替换为 try container.encode(String(value)) try container.encode(value) } }
步骤2:修改结构体属性注解
只需在需要适配的Double属性前添加@StringToDouble即可,无需修改其他逻辑:
public struct MyStruct: Encodable, Decodable { @StringToDouble public var amount: Double? public init(amount: Double? = nil) { self.amount = amount } }
补充说明
- 如果业务对数值精度要求极高,要避免
Double的浮点数精度丢失,可以将属性包装器内的Double替换为Swift原生的Decimal类型,Decimal(string: stringVal)可以完全匹配Python Decimal的精度。 - 若需要严格校验数值格式,可在解码失败时主动抛出
DecodingError,替代默认置为nil的逻辑。
内容的提问来源于stack exchange,提问作者Paul Bénétau
相关产品推荐
相关产品推荐

