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

iOS 13中JSONDecoder.convertFromSnakeCase失效?单元测试解码异常排查

解决iOS 13/Xcode 11下JSONDecoder convertFromSnakeCase解码失败的问题

我之前也碰到过类似的版本升级后解码异常的情况,结合你的代码、报错信息和场景,咱们来一步步拆解解决:

问题根源分析

你的DiscogsInfo结构体中,documentationUrl属性对应JSON里的documentation_url,按道理convertFromSnakeCase策略应该自动完成蛇形命名到驼峰命名的转换,但报错却显示找不到documentationUrl键,说明解码器并没有正确应用这个策略。

大概率是两个原因之一:

  • 解码器实例未正确复用:你可能在解码时临时创建了新的JSONDecoder,而没有使用已经配置好keyDecodingStrategy的那个实例——默认情况下新解码器的策略是.useDefaultKeys,自然无法匹配蛇形键。
  • iOS 13对策略的处理细节变化:虽然官方文档没明确标注,但iOS13对部分特殊命名的转换逻辑有更严格的要求,比如小写开头的蛇形键对应大写开头的驼峰属性时,可能出现转换失效。

具体解决方案

方案1:确保解码器策略被正确应用

先检查你的解码代码,务必复用同一个配置好策略的解码器实例:

// 全局/局部复用这个配置好的解码器
let jsonDecoder = JSONDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase

// 解码时直接使用这个实例
do {
    let discogsInfo = try jsonDecoder.decode(DiscogsInfo.self, from: jsonData)
    // 处理解析结果
} catch {
    print("解码失败:\(error)")
}

别在每次解码时都写let decoder = JSONDecoder(),这样会重置所有配置。

方案2:手动指定CodingKeys(最稳妥)

如果依赖系统策略不稳定,手动添加CodingKeys是彻底规避版本兼容性问题的方式,解码逻辑完全可控:

public struct DiscogsInfo: Codable {
    public var apiVersion: String?
    public var documentationUrl: URL
    public var hello: String
    public var statistics: Stats

    // 手动映射JSON键和属性名
    enum CodingKeys: String, CodingKey {
        case apiVersion = "api_version"
        case documentationUrl = "documentation_url"
        case hello
        case statistics
    }

    public struct Stats: Codable {
        public var labels: Int
        public var artists: Int
        public var releases: Int

        enum CodingKeys: String, CodingKey {
            case labels, artists, releases
        }
    }
}

这种方式不管系统策略怎么变,都能保证键名映射的准确性。

方案3:验证iOS 13策略的实际行为

可以写个极简测试用例,确认convertFromSnakeCase在iOS13下的表现:

struct TestModel: Codable {
    let documentationUrl: String
}

let testJson = #"{"documentation_url": "https://example.com"}"#.data(using: .utf8)!
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

do {
    let model = try decoder.decode(TestModel.self, from: testJson)
    print("解析成功:\(model.documentationUrl)")
} catch {
    print("解析失败:\(error)")
}

如果这个测试也失败,说明确实是iOS13的策略bug,此时方案2就是最优解。

总结

先排查解码器实例的复用问题,确认策略配置无误后如果仍报错,手动添加CodingKeys是最可靠的解决方式,能彻底避免系统版本带来的行为差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:08:47