Swift中Bool类型与其他类型JSON解码错误不一致问题
问题代码
import Foundation let json = """ { "property": null } """.data(using: .utf8)! struct Program<T: Decodable>: Decodable { let property: T static func decode() { do { try JSONDecoder().decode(Self.self, from: json) } catch { print("Error decoding \(T.self): \(error)\n") } } } Program<String>.decode() Program<Int>.decode() Program<[Double]>.decode() Program<[String: Int]>.decode() Program<Bool>.decode()
问题现象
运行上述代码后会出现明显的错误类型差异:
String、Int、数组、字典等类型解码非可选值遇到null时,均抛出valueNotFound错误,错误信息为Cannot get unkeyed decoding container -- found null value instead,符合文档预期;- 唯独
Bool类型抛出typeMismatch错误,错误信息为Expected to decode Bool but found null instead.,和其他类型的错误类型不一致。
原因解析
这是Swift标准库中不同类型的Decodable实现细节差异导致的:
- 对于
String、Int以及集合类型,解码逻辑会先检查当前JSON值是否为null,如果是且目标类型为非可选,就抛出valueNotFound错误; - 但
Bool的解码逻辑是直接尝试将JSON值转换为Bool,遇到null时直接判定为类型不匹配,因此抛出typeMismatch错误,没有针对null做特殊判断。
这属于标准库实现的路径差异,并非Bug。
统一错误类型的解决方案
如果希望Bool遇到null时也抛出valueNotFound错误,可以自定义Bool的解码逻辑:
extension Bool: Decodable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() guard let boolValue = try? container.decode(Bool.self) else { throw DecodingError.valueNotFound(Self.self, .init(codingPath: container.codingPath, debugDescription: "Expected to decode Bool but found null instead.")) } self = boolValue } }
修改后,Bool类型遇到null时就会和其他类型保持一致,抛出valueNotFound错误。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

