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()
For every case, except for Bool, we get valueNotFound("Cannot get unkeyed decoding container -- found null value instead") error. Which is correct, according to the documentation.
Only for Bool, for some reason, we get typeMismatch("Expected to decode Bool but found null instead.") error.
On Linux (fiddle),
[Double]produces avalueNotFoundand everything else produces atypeMismatch. This is consistent with the source of swift-core-libs-foundation, whereunkeyedContainer(which is called when decoding the array) throwsvalueNotFound(source):whereas
typeMismatchis thrown by the single value container created for decoding the "scalar" types (source).Because of this, I'd suspect
JSONDecoderon macOS is not purposefully implemented forBoolto throwtypeMismatchand the othersvalueNotFound. It seems to use theJSONSerializationAPI to decode the JSON to anNSDictionaryfirst. The behaviour ofBoolvs the other types could be quirk of as a consequence of that.I personally think the wording in the documentation for
typeMismatchandvalueNotFoundare loose enough that it would be "correct" to throw either, when encountering a null value.