Swift 4 Tableau Codable
j'ai donc une route API qui renvoie un tableau JSON d'objets. Par exemple:
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
j'essaie d'imaginer comment utiliser la nouvelle fonctionnalité codable dans Swift pour convertir ces deux objets dans une classe. Donc, si j'ai une classe de personnes codable, je voudrais prendre cette réponse et la faire me donner deux objets de personne.
J'utilise aussi Alamofire pour traiter les requêtes.
Comment puis-je faire cela? Jusqu'à présent, tout ce que j'ai vu a trait à la codable stuff permet seulement 1 objet. Et je n'ai vu aucune intégration avec Alamofire ou un framework web.
2 réponses
mise à jour concernant Alamofire 5: responseJSONDecodable
.
struct Person: Codable {
let firstName, lastName: String
let age: Int
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
}
Alamofire.request(request).responseJSONDecodable { (response: DataResponse<Person>) in
print(response)
}
Alamofire 4 n'ajoutera pas de support Codable pour le moment (voir #2177), vous pouvez utiliser cette extension à la place:https://github.com/Otbivnoe/CodableAlamofire.
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
""".data(using: .utf8)!
struct Person: Codable {
let firstName, lastName: String
let age: Int
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
}
let decoded = try! JSONDecoder().decode([Person].self, from: jsonData)
Exemple: http://swift.sandbox.bluemix.net/#/repl/59a4b4fad129044611590820
À L'Aide De CodableAlamofire:
let decoder = JSONDecoder()
Alamofire.request(url).responseDecodableObject(keyPath: nil, decoder: decoder) { (response: DataResponse<[Person]>) in
let persons = response.result.value
print(persons)
}
keypath
correspond au chemin d'accès où les résultats sont contenus dans la structure JSON. E. g:
{
"result": {
"persons": [
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
}
}
keypath
=>results.persons
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
keypath
=>nil
(vide keypath
lance une exception)
j'ai réussi à sérialiser la réponse des données aux objets codables.
comme tout ce que vous avez pu être familier avec la conversion d'objet json [String: String]
par exemple. Cet objet json doit être converti en Data
en utilisant json.data(using: .utf8)!
.
avec Alamofire, il est facile d'obtenir ce type de données (ou du moins ce genre de données a fonctionné pour moi, déjà compatible avec .utf8
chose), je peux utiliser ce déjà à la disposition de la fonction
func responseData(queue: DispatchQueue?, completionHandler: @escaping (DataResponse<Data>) -> Void) -> Self
alors il suffit d'utiliser ces données comme entrée pour l' Decoder
dans le completionHandler
let objek = try JSONDecoder().decode(T.self, from: data)
vous pouvez aussi faire ceci à une fonction de sérialisation générique, avec un petit ajustement, à partir de la documentation
Générique Réponse De La Sérialisation D'Un Objet
à cette modification
func responseCodable<T: Codable>(
queue: DispatchQueue? = nil,
completionHandler: @escaping (DataResponse<T>) -> Void)
-> Self
{
let responseSerializer = DataResponseSerializer<T> { request, response, data, error in
guard error == nil else { return .failure(BackendError.network(error: error!)) }
guard let data = data else {
return .failure(BackendError.objectSerialization(reason: "data is not valid"))
}
do{
let objek = try JSONDecoder().decode(T.self, from: data!)
return .success(objek)
} catch let e {
return .failure(BackendError.codableSerialization(error: e))
}
}
return response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
}
structure de L'échantillon
struct Fids: Codable {
var Status: Status?
var Airport: Airport?
var Record: [FidsRecord]
}
utilisez la fonction de cette façon
Alamofire.request("http://whatever.com/zzz").responseCodable { (response: DataResponse<Fids>) in
switch response.result{
case .success(let value):
print(value.Airport)
// MARK: do whatever you want
case .failure(let error):
print(error)
self.showToast(message: error.localizedDescription)
}
}