使用 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 参数的名称,因为我正在使用 keyDecodingStrategyhttp_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) }

考虑到 usercountrieslocations 是可解码的,

,您的解码方法和 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)