Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping Generic API Response Using Codable or ObjectMapper

I am facing a challenge regarding mapping a generic api responses against a model class using codable or object mapper. Suppose I have these api responses against different apis.

{
  "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
}

here user, locations and countries are separate codable/mapper classes.

I will have to construct a class like this

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

How I will construct my base class to handle these responses using one class or I will have construct different classes just to change "data" type according to value?

Any kind of help or suggestion will be highly appreciated.

Thanks

like image 872
Muhammad Awais Avatar asked Jun 22 '26 16:06

Muhammad Awais


1 Answers

Make generic constraint for you struct which says that T has to conform to Decodable and then use this type for specifing type of data

struct APIResponse<T: Decodable>: Decodable {
    var code, httpResponse: Int
    var success: Bool
    var data: T
}

struct User: Decodable {
    var name: String
}

note that I changed name of httpResponse parameter since I'm using keyDecodingStrategy which converts http_response to httpResponse


Then while decoding specify type of T

Single object

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) }

Array of objects

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) }
like image 165
Robert Dresler Avatar answered Jun 24 '26 04:06

Robert Dresler