For a given JSON like below:
{
"store": {
"animals": [
{
"type": "dog"
},
{
"type": "cat"
}
]
}
}
I can parse it with enum for type
like following:
final class AnimalStore: Decodable {
let store: Store
}
extension AnimalStore {
struct Store: Decodable {
let animals: [Animal]
}
}
extension AnimalStore.Store {
struct Animal: Decodable {
let type: AnimalType?
}
}
extension AnimalStore.Store.Animal {
enum AnimalType: String, Decodable {
case dog = "dog"
case cat = "cat"
//case unknown = how such a case could be implemented?
}
}
And also since it is optional; it would work fine if type
key value pair would be missing from json.
But I would like to have another case, lets call it unknown
so that if any given type is not dog or cat (string being something else),type would be initialised as unknown. Right now it crashes if a type, other than dog or cat is given.
How initialising with another type other than the ones given can be implemented with enum?
In other words, for a given type like: "type": "bird"
I would like type
to be initialised as unknown
.
Add the enum case with a string, you may as well use "unknown"
.
To convert non-matching strings to unknowns, you have to manually implement init(from decoder: Decoder)
at some point, either in your Animal or in AnimalType. I'd favour using AnimalType so that you don't have to manually decode any of the other properties of Animal.
enum AnimalType: String, Decodable {
case dog = "dog"
case cat = "cat"
case unknown = "unknown"
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
self = AnimalType(rawValue: string) ?? .unknown
}
}
If you did it in Animal
, you'd need something like:
// Decode everything else...
type = try? decoder.decode(AnimalType.self, forKey: .type) ?? .unknown