Reputation: 7008
I have a JSON object that always has text
, and sometime has a format
key and when it doesn't, I want to use the .regular
case for my SubStep.Format
enum.
I know I need to override the init
in SubStep
but how do I do it such that I can detect the format key, if it's nil, use .regular
, and then just decode the text
key that's always there?
Thanks
struct SubStep: Decodable {
enum Format: String, Decodable {
case bold = "bold"
case regular = "regular"
init(from decoder: Decoder) {
do {
let label = try decoder.singleValueContainer().decode(String.self)
self = Format(rawValue: label) ?? .regular
} catch {
self = .regular
}
}
}
let format: SubStep.Format
let text: String
init(from decoder: Decoder) throws {
// something in here
}
}
Upvotes: 0
Views: 290
Reputation: 130200
As an alternative solution, you don't have to insert the default value during parsing - you can use a computed property instead.
struct SubStep: Decodable {
enum Format: String, Decodable {
case bold
case regular
}
private let formatOptional: Format?
let text: String
private enum CodingKeys: String, CodingKey {
case formatOptional = "format"
case text
}
var format: Format {
return formatOptional ?? .regular
}
}
Upvotes: 1
Reputation: 54805
You don't need to create a custom init(from:)
method for Format
, you only need one for SubStep
. You need to use container.decodeIfPresent(_:forKey:)
to decode a key which might not be present in your JSON, in which case it returns nil
.
struct SubStep: Decodable {
enum Format: String, Decodable {
case bold
case regular
}
let format: SubStep.Format
let text: String
private enum CodingKeys: String, CodingKey {
case text, format
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.text = try container.decode(String.self, forKey: .text)
self.format = try container.decodeIfPresent(Format.self, forKey: .format) ?? .regular
}
}
Unrelated to your issue, but you don't need to provide a String
rawValue
for your enum
cases if their rawValue would exactly match the name of the case, the compiler will autosynthetise those for you.
Upvotes: 2