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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:48:01