Swift Codable 将空 json 解码为 nil 或空对象

Mak*_*ele 7 ios swift codable decodable

这是我的代码:

class LoginUserResponse : Codable {
    var result: String = ""
    var data: LoginUserResponseData?
    var mess: [String] = []
}

public class LoginUserResponseData : Codable {
    var userId = "0"
    var name = ""
}
Run Code Online (Sandbox Code Playgroud)

现在,调用服务器 API 我正在解析这样的响应(使用 Stuff 库来简化解析):

do {
    let loginUserResponse = try LoginUserResponse(json: string)
} catch let error {
    print(error)
}
Run Code Online (Sandbox Code Playgroud)

当我输入正确的密码时,我会得到这样的答案:

{"result":"success","data":{"userId":"10","name":"Foo"},"mess":["You're logged in"]}
Run Code Online (Sandbox Code Playgroud)

这很好,解析器工作正常。

提供错误密码时给出以下答案:

{"result":"error","data":{},"mess":["Wrong password"]}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,解析器失败了。它应该将数据设置为 nil,而是尝试将其解码为 LoginUserResponseData 对象。

我在使用改造的 Android 上使用相同的方法,它工作正常。我宁愿不想将所有字段都设为可选。

有没有办法让解析器将空的 json {} 视为 nil?或者将 LoginUserResponseData 设为非可选并且它只有默认值?我知道我可以为此创建一个自定义解析器,但我有大量这样的请求,它需要太多的额外工作。

Ars*_*nik 7

就这么简单!

class LoginUserResponse : Codable {
    var result: String = ""
    var data: LoginUserResponseData?
    var mess: [String] = []

    private enum CodingKeys: String, CodingKey {
        case result, data, mess
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        result = try values.decode(String.self, forKey: .result)
        mess = try values.decode([String].self, forKey: .mess)
        data = try? values.decode(LoginUserResponseData.self, forKey: .data)
    }
}

public class LoginUserResponseData : Codable {
    var userId = "0"
    var name = ""
}

let str = "{\"result\":\"success\",\"data\":{\"userId\":\"10\",\"name\":\"Foo\"},\"mess\":[\"You're logged in\"]}"
let str2 = "{\"result\":\"error\",\"data\":{},\"mess\":[\"Wrong password\"]}"

let decoder = JSONDecoder()
let result = try? decoder.decode(LoginUserResponse.self, from: str.data(using: .utf8)!)
let result2 = try? decoder.decode(LoginUserResponse.self, from: str2.data(using: .utf8)!)
dump(result)
dump(result2)
Run Code Online (Sandbox Code Playgroud)


Vit*_*nko 3

这是因为{}是一个空对象,但不是 nil。您有 2 个选择:

  1. 在服务器上更改为 return而null不是{}keydata
  2. 实现自定义初始化程序init(from: Decoder)并手动处理这种情况