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()
对于每种情况,除了
Bool
之外,我们都会收到 valueNotFound
(“无法获取未加密的解码容器 - 找到空值”)错误。根据文档,这是正确的。Bool
,由于某种原因,我们得到 typeMismatch
(“预期解码 Bool 但发现 null 相反。”) 错误。
在 Linux (fiddle) 上,
[Double] produces a
valueNotFoundand everything else produces a
typeMismatch. This is consistent with the source of [swift-core-libs-foundation][2], where
unkeyedContainer(which is called when decoding the array) throws
valueNotFound` (source):
@usableFromInline func unkeyedContainer() throws -> UnkeyedDecodingContainer {
switch self.json {
case .array(let array):
...
case .null:
throw DecodingError.valueNotFound([String: JSONValue].self, DecodingError.Context(
codingPath: self.codingPath,
debugDescription: "Cannot get unkeyed decoding container -- found null value instead"
))
default:
...
}
}
而
typeMismatch
是由为解码“标量”类型而创建的单值容器抛出的(source)。
func decode(_: Bool.Type) throws -> Bool {
guard case .bool(let bool) = self.value else {
throw self.impl.createTypeMismatchError(type: Bool.self, value: self.value)
}
return bool
}
因此,我怀疑 macOS 上的
JSONDecoder
并不是故意实现的,以便 Bool
抛出 typeMismatch
和其他 valueNotFound
。 macOS 上的 JSONDecoder
似乎首先使用 JSONSerialization
API 将 JSON 解码为 NSDictionary
。因此,这可能是一个怪癖。
我个人认为文档中
typeMismatch
和 valueNotFound
的措辞足够宽松,当遇到空值时,抛出其中任何一个都是“正确的”。