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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:43:09