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

Swift 4 JSON Codable遇"None"类型赋值报错求解决方案

哈哈,这个问题我前段时间刚踩过坑!后端用字符串"None"来表示空值,但我们的Codable模型属性是Int/Double这类非String类型,直接解析肯定会报错,因为类型完全不匹配。给你几个实用的解决思路,你可以根据自己的场景选:

思路1:自定义包装类型(最推荐,扩展性强)

针对需要处理"None"的类型,写一个通用的包装器来兼容字符串和目标类型的解析:

struct OptionalWrapper<T: Codable>: Codable {
    let value: T?
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        do {
            // 先尝试解析成目标类型
            value = try container.decode(T.self)
        } catch {
            // 解析失败就尝试读字符串
            let stringValue = try container.decode(String.self)
            if stringValue == "None" {
                value = nil
            } else {
                // 非"None"的字符串可以选择抛出错误,或者尝试转成目标类型
                throw DecodingError.dataCorruptedError(in: container, debugDescription: "Expected \(T.self) or 'None' string")
            }
        }
    }
}

然后在模型里直接用这个包装器代替可选类型:

struct User: Codable {
    let id: OptionalWrapper<Int>
    let balance: OptionalWrapper<Double>
}

如果只需要针对某一种类型处理,也可以写非泛型的版本,比如OptionalInt、OptionalDouble,逻辑是一样的。

思路2:全局替换"None"为null(简单粗暴,适合统一场景)

如果后端所有的空值都是用"None"表示,没有其他地方需要保留这个字符串,那可以先把JSON里的"None"替换成null再解析:

// 假设你拿到的是JSON Data
guard let jsonString = String(data: jsonData, encoding: .utf8) else {
    // 处理数据转换失败
    return
}
// 替换所有"None"字符串为null
let modifiedJsonString = jsonString.replacingOccurrences(of: "\"None\"", with: "null")
guard let modifiedData = modifiedJsonString.data(using: .utf8) else {
    return
}

let decoder = JSONDecoder()
do {
    let model = try decoder.decode(YourTargetModel.self, from: modifiedData)
    // 处理解析后的模型
} catch {
    print("解析错误:\(error)")
}

注意:这个方法要谨慎用,如果你的JSON里有某个字段本来就需要存储"None"字符串,会被误替换成null。

思路3:模型内手动处理(适合个别字段)

如果只有少数几个字段存在"None"的情况,直接在模型的自定义解码方法里处理更灵活:

struct Product: Codable {
    let price: Double?
    let stockCount: Int?
    
    enum CodingKeys: String, CodingKey {
        case price, stockCount
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 处理price字段
        do {
            price = try container.decode(Double.self, forKey: .price)
        } catch {
            let priceStr = try container.decode(String.self, forKey: .price)
            price = priceStr == "None" ? nil : Double(priceStr)
        }
        
        // 处理stockCount字段
        do {
            stockCount = try container.decode(Int.self, forKey: .stockCount)
        } catch {
            let stockStr = try container.decode(String.self, forKey: .stockCount)
            stockCount = stockStr == "None" ? nil : Int(stockStr)
        }
    }
}

这种方式不用额外写包装类型,针对性处理个别字段,代码也更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:03:01