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

时间:2019-01-28 07:09:51

标签: ios swift mapping codable objectmapper

我面临着使用可编码或对象映射器将通用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 : ??
}

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

任何帮助或建议将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:2)

对您的结构进行通用约束,该约束说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_responsehttpResponse


然后在解码时指定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) }

答案 1 :(得分:1)

考虑到APIResponseusercountries是可解码的,您的解码方法和locations看起来像这样,

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)