How to use decodable protocol with custom type values in Swift?

本秂侑毒 提交于 2020-01-05 04:18:50

问题


I have 2 types of response depending on my reuest: First one:

{
    "status": "success"
    "data": {
        "user_id": 2,
        "user_name": "John"      
    }
}

And second one is:

{
    "status": "error",
    "data": [],
}

I am using struct like that:

struct ValyutaListData:Decodable {
    let status: String? 
    let data: [String]?
}

But if response is first type response, then an error occured. Because In first Type response data is not array. It is Json object. Then i use structure like that:

struct ValyutaListData:Decodable {
    let status: String? 
    let data: Persondata?
}

struct Persondata: Decodable{
    let user_id: Int?
    let user_name: String?
}

If response is second type response, the error will be occured. What kind of of structure should use for dynamic type JSONs? Thanks.


回答1:


One reasonable solution is an enum with associated type(s)

struct User : Decodable {
    let userId: Int
    let userName: String
}

enum Result : Decodable {
    case success(User), failure

    enum CodingKeys: String, CodingKey { case status, data }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let status = try container.decode(String.self, forKey: .status)
        if status == "success" {
            let userData = try container.decode(User.self, forKey: .data)
            self = .success(userData)
        } else {
            self = .failure
        }
    }
}

And use it

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let result = try decoder.decode(Result.self, from: data)
    switch result {
      case .success(let user): print(user)
      case .failure: print("An error occurred")
    }
} catch { print(error) }


来源:https://stackoverflow.com/questions/58192100/how-to-use-decodable-protocol-with-custom-type-values-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!