如何让Swift JSONDecoder处理可选属性类型不匹配时不解码失败?
这个问题我之前也碰到过,默认的Codable对可选属性的类型校验还是很严格的——哪怕属性是可选的,只要JSON里对应字段的类型不匹配,整个解码流程就会崩掉。下面给你两种解决思路,按需选就行:
方法1:针对单个结构体手动实现解码逻辑
如果只是少数几个属性需要处理,直接在结构体里自定义init(from:)方法,对目标属性做容错处理就好:
struct Object: Codable { let year: Int? // 假设还有其他属性,比如: let name: String enum CodingKeys: String, CodingKey { case year, name } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 处理year:尝试解码成Int,失败就设为nil year = try? container.decode(Int.self, forKey: .year) // 其他属性正常解码(如果是必填项就用try,可选的话也可以用try?) name = try container.decode(String.self, forKey: .name) } }
这里用try?替代try,如果解码失败(比如类型不匹配),就会返回nil,不会抛出错误中断整个解码流程。
方法2:全局扩展让所有可选属性支持容错解码
如果你有很多结构体的可选属性都需要这种容错逻辑,可以给Optional写一个全局扩展,一次性解决所有可选Decodable类型的问题:
extension Optional: Decodable where Wrapped: Decodable { public init(from decoder: Decoder) throws { do { let container = try decoder.singleValueContainer() self = try container.decode(Wrapped.self) } catch { // 解码失败时直接设为nil,也可以在这里加日志方便调试 self = nil // print("Failed to decode optional \(Wrapped.self): \(error)") } } }
这样一来,所有的可选Decodable属性(不管是Int?、String?还是自定义类型的可选),只要JSON里对应字段的类型不匹配,都会自动被解析成nil,不会导致整个解码失败。
测试验证
用你的问题场景测试一下:
// 类型不匹配的JSON let badJson = """ { "year": "maybe string value", "name": "Test Object" } """ let data = badJson.data(using: .utf8)! do { let object = try JSONDecoder().decode(Object.self, from: data) print(object.year) // 输出 nil print(object.name) // 输出 "Test Object" } catch { // 不会走到这里,解码成功 print(error) }
不管用哪种方法,这个JSON都能成功解码,year会被设为nil,其他属性正常解析。
内容的提问来源于stack exchange,提问作者user25917
相关产品推荐
相关产品推荐

