Отображение общего ответа API с использованием Codable или ObjectMapper - PullRequest
0 голосов
/ 28 января 2019

Я сталкиваюсь с проблемой, связанной с сопоставлением ответов общего 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 голосов
/ 28 января 2019

Ваш метод декодирования и APIResponse будут выглядеть следующим образом, учитывая, что user, countries, 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) 
0 голосов
/ 28 января 2019

Создайте для вас общее ограничение, в котором говорится, что T должно соответствовать Decodable, а затем используйте этот тип для указания типа data

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

struct User: Decodable {
    var name: String
}

noteчто я изменил имя параметра 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) }
...