Swift-Decodable无法使用可选值进行解码

时间:2019-12-14 12:39:33

标签: json swift decode codable

我正在尝试向后端提出一个简单的登录请求。仅当登录成功后,后端才会返回由状态码,每次字符串消息和访问令牌组成的JSON对象。
为此,我创建了以下struct

struct AuthResponse: Decodable {
    enum CodingKeys: String, CodingKey {
        case code, message
        case accessToken = "access_token"
    }

    let code: Int, message: String, accessToken: String?
}

当登录失败并且服务器未发送访问令牌时,AuthResponse对象将设法正确解码,nil属性的accessToken就像我希望如此。例如,对于以下响应,解码成功:

  

code = 400;
   message =“用户未注册”;

但是对于带有访问令牌的响应,例如:

  

“ access_token” = TheAccessToken ;
      代码= 200;
      message =“登录成功”;

AuthResponse对象不会解码。

为什么会这样?这与accessToken属性是可选属性有关吗?我还尝试了覆盖解码初始化程序并实现decodeIfPresent(_:forKey:)并展开属性,但两者似乎都没有帮助。
预先感谢。

1 个答案:

答案 0 :(得分:2)

代码一定不会因您提供的信息而失败。

请在error块中打印catch实例,并将其添加到您的问题中。

尽管如此,一个复杂的替代方法(没有任何可选方法)是带有关联类型的枚举。成功返回令牌,失败返回代码和消息

enum AuthResponse: Decodable {

    case success(String), failure(Int, String)

    private enum CodingKeys : String, CodingKey { case code, message, accessToken = "access_token" }

    init(from decoder : Decoder) throws
    {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            let code = try container.decode(Int.self, forKey: .code)
            if code == 200 {
                let token = try container.decode(String.self, forKey: .accessToken)
                self = .success(token)
            } else {
                let message = try container.decode(String.self, forKey: .message)
                self = .failure(code, message)
            }
        }
    }
}

并使用它

let result = try JSONDecoder().decode(AuthResponse.self, from: data)
switch result {
   case .success(let token): print(token)
   case .failure(let code, let message): print(code, message)
}