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

Swift 4 Codable解码含混合类型JSON数组问题求助

解决Swift Codable解码混合Double与空字符串二维数组的问题

嗨,这个问题我之前在项目里也碰到过——Codable对这种同一位置可能返回数值或空字符串的混合类型数组确实不太友好,直接用[[Any]]或者[[Double]]都走不通,不过我们可以通过自定义Codable包装类型来完美解决这个问题,具体方案如下:

1. 自定义处理单个元素的Codable类型

我们先创建一个DoubleOrEmptyString结构体,专门处理每个位置可能是Double或者空字符串的情况,实现Codable协议来自定义解码/编码逻辑:

struct DoubleOrEmptyString: Codable {
    let value: Double? // 用可选类型接收,空字符串对应nil
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        // 先尝试解码成Double
        do {
            value = try container.decode(Double.self)
        } catch {
            // 解码Double失败,尝试解码字符串
            let stringValue = try container.decode(String.self)
            if stringValue.isEmpty {
                // 是空字符串就设为nil
                value = nil
            } else {
                // 非空字符串的话,抛出原错误(比如接口返回了其他无效值)
                throw error
            }
        }
    }
    
    // 如果需要编码回原格式,实现encode方法
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if let validValue = value {
            try container.encode(validValue)
        } else {
            try container.encode("")
        }
    }
}

2. 定义接口响应模型

接下来把你的响应模型里的data字段定义为[[DoubleOrEmptyString]]类型即可:

struct ApiResponse: Codable {
    let data: [[DoubleOrEmptyString]]
}

3. 解码使用示例

现在就可以正常用JSONDecoder解码接口返回的数据了,处理的时候可以通过value属性获取可选的Double值:

// 假设jsonData是接口返回的Data数据
do {
    let response = try JSONDecoder().decode(ApiResponse.self, from: jsonData)
    
    // 遍历处理二维数组
    for row in response.data {
        for element in row {
            print(element.value ?? "该位置为空字符串")
        }
    }
} catch {
    print("解码失败:\(error.localizedDescription)")
}

可选优化:把空字符串转为默认值0

如果你希望把空字符串直接转换成0.0而不是可选值,可以修改DoubleOrEmptyString的逻辑:

struct DoubleOrEmptyString: Codable {
    let value: Double // 非可选类型,空字符串对应0.0
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            value = try container.decode(Double.self)
        } catch {
            let stringValue = try container.decode(String.self)
            value = stringValue.isEmpty ? 0.0 : Double(stringValue) ?? 0.0
            // 这里也可以根据需求处理非空但非数值的字符串,比如直接抛出错误
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if value == 0.0 {
            try container.encode("")
        } else {
            try container.encode(value)
        }
    }
}

这个方案的核心就是把混合类型的解码逻辑封装到自定义类型里,让Codable能正确识别每个元素的类型,同时保持模型的类型安全性。

内容的提问来源于stack exchange,提问作者Simon Z.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:45:52