Open
Description
Previous ID | SR-7404 |
Radar | rdar://problem/39354522 |
Original Reporter | swillits (JIRA User) |
Type | Bug |
Environment
Xcode 9.3
Swift 4.1
Additional Detail from JIRA
Votes | 3 |
Component/s | Foundation |
Labels | Bug, Codable |
Assignee | None |
Priority | Medium |
md5: d0185b472c3142092e89fd809ebaa821
Issue Description:
JSONEncoder can encode a nil single value Optional<String> as JSON "null", but JSONDecoder does is unable to interpret the null correctly.
Consider:
struct Foo: Codable {
struct Value<T: Codable>: Codable {
var value: T
init(default def: T) {
value = def
}
init(from decoder: Decoder) throws {
let container = try! decoder.singleValueContainer()
value = try! container.decode(T.self)
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try! container.encode(value)
}
}
var test = Value<String?>(default: nil)
}
var f1 = Foo()
let data = try! JSONEncoder().encode(f1)
print(String(data: data, encoding: .utf8)!) // {"test":null}
let f2 = try! JSONDecoder().decode(Foo.self, from: data)
When the nil Optional<String> value is encoded, it is encoded as a single-value null as expected.
{"test":null}
But when decoding, an error is thrown:
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.Optional<Swift.String>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "test", intValue: nil)], debugDescription: "Expected Optional<String> but found null value instead.", underlyingError: nil)): file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-902.0.48/src/swift/stdlib/public/core/ErrorType.swift, line 184
Note that when switching singleValueContainer to unkeyedContainer, there is no similar error, but the encoded json then looks like: {"test":[null]}