【问题标题】:Swift - Decodable fails to decode with an optional valueSwift - Decodable 无法使用可选值解码
【发布时间】:2019-12-14 12:39:33
【问题描述】:

我正在尝试向后端发出一个简单的登录请求。后端返回一个 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 属性,正如我所期望的那样。例如,以下响应解码成功:

代码 = 400;
message = "用户未注册";

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

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

AuthResponse 对象没有解码失败。

为什么会这样?这是否与 accessToken 属性是可选的这一事实有关?我也尝试过覆盖解码初始化程序并实现decodeIfPresent(_:forKey:) 并解开属性,但似乎都没有帮助。
提前致谢。

【问题讨论】:

  • 这里的目的是什么?你想达到什么目的?好像没看懂
  • 您应该考虑为此使用某种Result。但如果你希望它是nillet accessToken: String? 就足够了。

标签: json swift decode codable


【解决方案1】:

代码不能因您提供的信息而失败。

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

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

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

【讨论】:

  • 原来问题与后端有关,代码有时以 int 形式返回,有时以字符串形式返回。不过感谢您的回答,这是一个很好的解决方案。
猜你喜欢
  • 2018-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 2018-10-21
相关资源
最近更新 更多