How do I make an enum Decodable in swift 4?

前端 未结 8 674
死守一世寂寞
死守一世寂寞 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条回答
  •  北海茫月
    2020-11-28 20:59

    How to make enums with associated types conform to Codable

    This answer is similar to @Howard Lovatt's but avoids creating a PostTypeCodableForm struct and instead uses the KeyedEncodingContainer type provided by Apple as a property on Encoder and Decoder, which reduces boilerplate.

    enum PostType: Codable {
        case count(number: Int)
        case title(String)
    }
    
    extension PostType {
    
        private enum CodingKeys: String, CodingKey {
            case count
            case title
        }
    
        enum PostTypeCodingError: Error {
            case decoding(String)
        }
    
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            if let value = try? values.decode(Int.self, forKey: .count) {
                self = .count(number: value)
                return
            }
            if let value = try? values.decode(String.self, forKey: .title) {
                self = .title(value)
                return
            }
            throw PostTypeCodingError.decoding("Whoops! \(dump(values))")
        }
    
        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            switch self {
            case .count(let number):
                try container.encode(number, forKey: .count)
            case .title(let value):
                try container.encode(value, forKey: .title)
            }
        }
    }
    

    This code works for me on Xcode 9b3.

    import Foundation // Needed for JSONEncoder/JSONDecoder
    
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    let decoder = JSONDecoder()
    
    let count = PostType.count(number: 42)
    let countData = try encoder.encode(count)
    let countJSON = String.init(data: countData, encoding: .utf8)!
    print(countJSON)
    //    {
    //      "count" : 42
    //    }
    
    let decodedCount = try decoder.decode(PostType.self, from: countData)
    
    let title = PostType.title("Hello, World!")
    let titleData = try encoder.encode(title)
    let titleJSON = String.init(data: titleData, encoding: .utf8)!
    print(titleJSON)
    //    {
    //        "title": "Hello, World!"
    //    }
    let decodedTitle = try decoder.decode(PostType.self, from: titleData)
    

提交回复
热议问题