如何准备 API 响应以在 swift 中与 jsonDecoder 一起使用
Posted
技术标签:
【中文标题】如何准备 API 响应以在 swift 中与 jsonDecoder 一起使用【英文标题】:how prepare API response to use with jsonDecoder in swift 【发布时间】:2019-02-02 20:15:43 【问题描述】:当我使用 Alamofire 调用 API 并从服务器获取响应时,我想使用来自 json 的“数据”对象
此数据来自 API
"code": 200,
"hasError": false,
"data": [
"userSession": "43a1bd70-26bf-11e9-9ccd-00163eaf6bb4"
],
"message": "ok"
我想将data
映射到我的AuthModel
这是我的AuthModel
:
struct AuthModel: Codable
let userSession: String
enum CodingKeys: String, CodingKey
case userSession = "userSession"
我编写了这行代码,但它不起作用:
if let responseObject = response.result.value as? Dictionary<String,Any>
if let hasError = responseObject["hasError"] as? Bool
guard !hasError else return
do
let decoder = JSONDecoder()
let authModel = try decoder.decode(AuthModel.self, from: responseObject["data"])
catch
print("Parse Error: ",error)
这不起作用,因为responseObject["data"]
不是 NSData 类型
无法将“[String : Any]”类型的值转换为预期的参数类型“Data”
【问题讨论】:
【参考方案1】:我认为您的 API 响应是一种模式,表明:
我们有什么问题(错误)吗? 我们有预期的数据吗?基于这些,我们可以使用Enum
和Generics
。例如:
class ResponseObject<T: Codable>: Codable
private var code : Int
private var hasError : Bool
private var message : String
private var data : T?
var result: Result
guard !hasError else return .error(code, message)
guard let data = data else return .error(0, "Data is not ready.")
return .value(data)
enum Result
case error(Int, String)
case value(T)
我们可以将ResponseObject
与我们预期的data
一起使用:
let responseString = """
"code": 200,
"hasError": false,
"data": [
"userSession": "43a1bd70-26bf-11e9-9ccd-00163eaf6bb4"
],
"message": "ok"
"""
class AuthObject: Codable
var userSession : String
if let jsonData = responseString.data(using: .utf8)
do
//ResponseObject<[AuthObject]> means: if we don't have error, the `data` object in response, will represent `[AuthObject]`.
let responseObject = try JSONDecoder().decode(ResponseObject<[AuthObject]>.self, from: jsonData)
//Using ResponseObject.Result Enum: We have error with related code and message, OR, we have our expected data.
switch responseObject.result
case .error(let code, let message):
print("Error: \(code) - \(message)")
case .value(let authObjects):
print(authObjects.first!.userSession)
catch
print(error.localizedDescription)
【讨论】:
【参考方案2】:例如获取Data
响应而不是反序列化的Dictionary
Alamofire.request(url).responseData response in
解码
let decoder = JSONDecoder()
let authModel = try decoder.decode(AuthModel.self, from: response.data!)
进入这些结构
struct AuthModel : Decodable
let code : Int
let hasError : Bool
let message : String
let data : [Session]
struct Session : Decodable
let userSession: String
所有的 CodingKey 都是合成的。
【讨论】:
发誓,这个 api 响应是所有 API 的模式,所以我不能在我的所有模型中始终使用代码、hasError、消息、数据 我刚刚回答了这个问题。以上是关于如何准备 API 响应以在 swift 中与 jsonDecoder 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django API GET 请求中与 websocket 通信?
如何设置正确的 Ruby 版本以在 Aptana 3 中与我的 Rails 5 项目一起使用?