使用 Codable 或 ObjectMapper 映射通用 API 响应
Mapping Generic API Response Using Codable or ObjectMapper
我面临着使用可编码或对象映射器将通用 api 响应映射到模型 class 的挑战。假设我有针对不同 api 的这些 api 响应。
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : user
}
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : locations
}
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : countries
}
此处用户、位置和国家/地区是分开的 codable/mapper classes.
我将不得不构建一个像这样的 class
struct APIResponse : Codable {
let success : Bool?
let http_response : Int?
let code : Int?
let data : ??
}
我将如何构建我的基础 class 来使用一个 class 来处理这些响应,或者我将构建不同的 classes 只是为了根据以下内容更改 "data" 类型值?
我们将不胜感激任何形式的帮助或建议。
谢谢
为你的结构创建通用约束,表示 T
必须符合 Decodable
,然后使用此类型指定 data
的类型
struct APIResponse<T: Decodable>: Decodable {
var code, httpResponse: Int
var success: Bool
var data: T
}
struct User: Decodable {
var name: String
}
请注意,我更改了 httpResponse
参数的名称,因为我正在使用 keyDecodingStrategy
将 http_response
转换为 httpResponse
然后在解码时指定T
的类型
单个对象
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let responses = try decoder.decode([APIResponse<User>].self, from: data)
let user = responses[0].data /* data of type `User` of specific response */
} catch { print(error) }
对象数组
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let responses = try decoder.decode([APIResponse<[User]>].self, from: data)
let users = responses[0].data /* data of type `[User]` of specific response */
} catch { print(error) }
考虑到 user
、countries
、locations
是可解码的,
,您的解码方法和 APIResponse
将看起来像这样
struct APIResponse<T: Decodable>: Decodable {
var data: T?
var code: Int
var success: Bool
var http_response: Int
}
func decode<T: Decodable>(data: Data, ofType: T.Type) -> T? {
do {
let decoder = JSONDecoder()
let res = try decoder.decode(APIResponse<T>.self, from: data)
return res.data
} catch let parsingError {
print("Error", parsingError)
}
return nil
}
用法
let data = Data() // From the network api
//User
let user = decode(data, ofType: User.self)
// Countries
let countries = decode(data, ofType: [Country].self)
// Locations
let locations = decode(data, ofType: [Location].self)
我面临着使用可编码或对象映射器将通用 api 响应映射到模型 class 的挑战。假设我有针对不同 api 的这些 api 响应。
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : user
}
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : locations
}
{
"code" : 0,
"http_response" : 200,
"success" : true,
"data" : countries
}
此处用户、位置和国家/地区是分开的 codable/mapper classes.
我将不得不构建一个像这样的 class
struct APIResponse : Codable {
let success : Bool?
let http_response : Int?
let code : Int?
let data : ??
}
我将如何构建我的基础 class 来使用一个 class 来处理这些响应,或者我将构建不同的 classes 只是为了根据以下内容更改 "data" 类型值?
我们将不胜感激任何形式的帮助或建议。
谢谢
为你的结构创建通用约束,表示 T
必须符合 Decodable
,然后使用此类型指定 data
struct APIResponse<T: Decodable>: Decodable {
var code, httpResponse: Int
var success: Bool
var data: T
}
struct User: Decodable {
var name: String
}
请注意,我更改了 httpResponse
参数的名称,因为我正在使用 keyDecodingStrategy
将 http_response
转换为 httpResponse
然后在解码时指定T
单个对象
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let responses = try decoder.decode([APIResponse<User>].self, from: data)
let user = responses[0].data /* data of type `User` of specific response */
} catch { print(error) }
对象数组
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let responses = try decoder.decode([APIResponse<[User]>].self, from: data)
let users = responses[0].data /* data of type `[User]` of specific response */
} catch { print(error) }
考虑到 user
、countries
、locations
是可解码的,
APIResponse
将看起来像这样
struct APIResponse<T: Decodable>: Decodable {
var data: T?
var code: Int
var success: Bool
var http_response: Int
}
func decode<T: Decodable>(data: Data, ofType: T.Type) -> T? {
do {
let decoder = JSONDecoder()
let res = try decoder.decode(APIResponse<T>.self, from: data)
return res.data
} catch let parsingError {
print("Error", parsingError)
}
return nil
}
用法
let data = Data() // From the network api
//User
let user = decode(data, ofType: User.self)
// Countries
let countries = decode(data, ofType: [Country].self)
// Locations
let locations = decode(data, ofType: [Location].self)