New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-5981] Decodable: Decoding TimeZone within class hierarchy leads to bad container #48540
Comments
@itaiferber, another for you. |
Comment by Adrian Schoenig (JIRA) A little bit more on this: when I debugged this, stepping through the `decode` call in the superclass and looking at the container, it is indeed missing the coding key in question (`primitive`) and instead has the coding keys of the struct - rather than the coding keys of the class being decoded. |
This can be pared down a little bit (because it actually doesn't have much to do with the class hierarchy): import Foundation
struct TimeZoneField : Decodable {
let timeZone: TimeZone
private enum CodingKeys : String, CodingKey {
case timeZone
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
timeZone = try container.decode(TimeZone.self, forKey: .timeZone)
} catch DecodingError.typeMismatch(_, _) {
let identifier = try container.decode(String.self, forKey: .timeZone)
timeZone = TimeZone(identifier: identifier)!
}
}
}
struct X : Decodable {
private enum CodingKeys : String, CodingKey {
case a, b
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let a = try container.decode(TimeZoneField.self, forKey: .a)
// Works
let b = try container.decode(Double.self, forKey: .b)
// Does not work:
// let container2 = try decoder.container(keyedBy: CodingKeys.self)
// let b = try container2.decode(Double.self, forKey: .b)
print("a: \(a)")
print("b: \(b)")
}
}
let json = "{ \"a\": { \"timeZone\": \"Australia/Sydney\" }, \"b\": 34.2 }".data(using: .utf8)!
let x = try JSONDecoder().decode(X.self, from: json) This doesn't appear to happen if |
@swift-ci Create |
Comment by Thorsten Karrer (JIRA) Probably the same cause as SR-6563. If you do not let the first call to container.decode() in TimeZoneField.init(from: ) fail (e.g. by trying decoding by identifier first, then try decoding the timezone directly in the catch block), it works. Smells like the broken container stack after exiting the scope via try before popping the top element (see comments in SR-6563). |
Attachment: Download
Environment
Tested in Xcode Version 9.0 (9A235) on macOS 10.12.6.
Additional Detail from JIRA
md5: 3fcd4b23dd102bfc9d281ab771963642
duplicates:
Issue Description:
I have this setup:
Struct S with a TimeZone field
Class A has a primitive field
Class B is a subclass of A and adds a field of type S
Decoding A succeeds, decoding S succeeds, but decoding B fails as the primitive field can't be found anymore:
It works as expected when changing the TimeZone field to some other type. It also works when adding that struct directly to A and not using the class hierarchy.
Playground with sample code to reproduce the issue is attached.
The text was updated successfully, but these errors were encountered: