How do I make an enum Decodable in swift 4?

前端 未结 8 681
死守一世寂寞
死守一世寂寞 2020-11-28 20:16
enum PostType: Decodable {

    init(from decoder: Decoder) throws {

        // What do i put here?
    }

    case Image
    enum CodingKeys: String, CodingKey {
          


        
8条回答
  •  萌比男神i
    2020-11-28 21:18

    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)")
    

提交回复
热议问题