【问题标题】:Mapping Generic API Response Using Codable or ObjectMapper使用 Codable 或 ObjectMapper 映射通用 API 响应
【发布时间】:2019-06-21 03:57:24
【问题描述】:

我在使用可编码或对象映射器将通用 api 响应映射到模型类方面面临挑战。假设我有针对不同 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
}

这里的用户、位置和国家是单独的可编码/映射器类。

我将不得不构建一个这样的类

struct APIResponse : Codable {
    let success : Bool?
    let http_response : Int?
    let code : Int?
    let data : ??
}

我将如何构造我的基类以使用一个类来处理这些响应,或者我将构造不同的类只是为了根据值更改“数据”类型?

我们将不胜感激任何形式的帮助或建议。

谢谢

【问题讨论】:

标签: ios swift mapping codable objectmapper


【解决方案1】:

为你的结构创建通用约束,表示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) }

【讨论】:

    【解决方案2】:

    考虑到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) 
    

    【讨论】:

      猜你喜欢
      • 2016-12-31
      • 1970-01-01
      • 2020-09-27
      • 2019-02-12
      • 2018-03-28
      • 2017-08-20
      • 1970-01-01
      • 2017-08-21
      • 2019-04-06
      相关资源
      最近更新 更多