Details
- Xcode 12.0.1 (12A7300)
- Swift 5.3
Solution
import Foundation
enum DecodableEnum where Enum.RawValue == String {
case value(Enum)
case error(DecodingError)
var value: Enum? {
switch self {
case .value(let value): return value
case .error: return nil
}
}
var error: DecodingError? {
switch self {
case .value: return nil
case .error(let error): return error
}
}
enum DecodingError: Error {
case notDefined(rawValue: String)
case decoding(error: Error)
}
}
extension DecodableEnum: Decodable {
init(from decoder: Decoder) throws {
do {
let rawValue = try decoder.singleValueContainer().decode(String.self)
guard let layout = Enum(rawValue: rawValue) else {
self = .error(.notDefined(rawValue: rawValue))
return
}
self = .value(layout)
} catch let err {
self = .error(.decoding(error: err))
}
}
}
Usage sample
enum SimpleEnum: String, Codable {
case a, b, c, d
}
struct Model: Decodable {
let num: Int
let str: String
let enum1: DecodableEnum
let enum2: DecodableEnum
let enum3: DecodableEnum
let enum4: DecodableEnum?
}
let dictionary: [String : Any] = ["num": 1, "str": "blablabla", "enum1": "b", "enum2": "_", "enum3": 1]
let data = try! JSONSerialization.data(withJSONObject: dictionary)
let object = try JSONDecoder().decode(Model.self, from: data)
print("1. \(object.enum1.value)")
print("2. \(object.enum2.error)")
print("3. \(object.enum3.error)")
print("4. \(object.enum4)")