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.

12
demandé sur rmaddy 2017-08-29 03:07:10

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)

13
répondu nathan 2018-05-30 19:00:29

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)
        }
    }
0
répondu abbawssdsad 2017-11-18 06:14:41