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

使用Decodable解析JSON时,经纬度变量存在双类型解析问题

解决Decodable解析混合类型经纬度的问题

这问题我之前对接后端API时也踩过坑!这种同一字段返回不同类型的情况确实很棘手,但用Swift的Decodable协议完全能优雅解决,给你两个实用方案:

方案一:自定义可解码的坐标类型(推荐)

我们可以创建一个专门处理Int/String转Double的Coordinate类型,把解码逻辑封装进去,这样主结构体的代码会更清爽:

struct Coordinate: Decodable {
    let value: Double
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        // 先尝试解析为整数类型(比如无数据时的0)
        if let intValue = try? container.decode(Int.self) {
            value = Double(intValue)
            return
        }
        
        // 失败则尝试解析为字符串,再转成Double
        let stringValue = try container.decode(String.self)
        guard let doubleValue = Double(stringValue) else {
            throw DecodingError.dataCorruptedError(
                in: container,
                debugDescription: "无法将坐标字符串「\(stringValue)」转换为Double类型"
            )
        }
        value = doubleValue
    }
}

然后在你的响应结构体里直接使用这个类型,还可以加计算属性快速获取Double值:

struct LocationResponse: Decodable {
    let latitude: Coordinate
    let longitude: Coordinate
    
    // 便捷属性,直接拿到经纬度的Double值
    var lat: Double { latitude.value }
    var lon: Double { longitude.value }
    
    // 还可以加个判断是否为有效地理数据的属性
    var hasValidLocation: Bool {
        lat != 0.0 && lon != 0.0
    }
}

方案二:用枚举处理多类型

如果需要保留原始类型的信息(比如区分是Int的0还是字符串的"0"),可以用枚举来实现:

enum CoordinateEnum: Decodable {
    case integer(Int)
    case string(String)
    
    // 提供转换为Double的便捷属性
    var doubleValue: Double? {
        switch self {
        case .integer(let int):
            return Double(int)
        case .string(let str):
            return Double(str)
        }
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        if let intVal = try? container.decode(Int.self) {
            self = .integer(intVal)
        } else if let strVal = try? container.decode(String.self) {
            self = .string(strVal)
        } else {
            throw DecodingError.dataCorruptedError(
                in: container,
                debugDescription: "不支持的坐标类型"
            )
        }
    }
}

使用时在结构体里声明let latitude: CoordinateEnum,之后通过latitude.doubleValue获取数值即可。

这两种方案都能完美解决你遇到的解码错误问题,个人更推荐方案一,因为它直接把类型统一成了Double,后续业务逻辑处理起来更省心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:58:23