使用 Codable 或 ObjectMapper 映射通用 API 响应

Posted

技术标签:

【中文标题】使用 Codable 或 ObjectMapper 映射通用 API 响应【英文标题】:Mapping Generic API Response Using Codable or ObjectMapper 【发布时间】: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 : ??

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

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

谢谢

【问题讨论】:

***.com/questions/52681385/… 【参考方案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) 

【讨论】:

以上是关于使用 Codable 或 ObjectMapper 映射通用 API 响应的主要内容,如果未能解决你的问题,请参考以下文章

如果某些东西符合 Codable ,它会永远无法被编码或解码吗?

在 swift 中对动态键和动态对象使用 Codable

FullAuditedEntity、ObjectMapper:创建新条目或删除时的 CreatorUserId Null

如何一起使用Codable和Coredata?

Swift:如何将带有 Alamofilre 或 SwiftyJSON 的 JSON 字符串转换为 ObjectMapper?

ObjectMapper - 线程安全和性能的最佳实践