2017-09-21 5 views
0

J'essaye d'implémenter le nouveau protocole Decodable de Swift 4 et j'ai du mal à l'approcher.Utilisation du protocole Decodable de Swift 4 pour la réponse du serveur JSON imbriqué

Ceci est ma réponse du serveur JSON:

{ 
    "success": true, 
    "errorCode": 0, 
    "message": "Succcess", 
    "data": { 
    "name": "Logan Howlett", 
    "nickname": "The Wolverine", 
    "image": "http://heroapps.co.il/employee-tests/ios/logan.jpg", 
    "dateOfBirth": 1880, 
    "powers": [ 
     "Adamantium Bones", 
     "Self-Healing", 
     "Adamantium Claws" 
    ], 
    "actorName": "Hugh Jackman", 
    "movies": [ 
     { 
     "name": "X-Men Origins: Wolverine", 
     "year": 2009 
     }, 
     { 
     "name": "The Wolverine", 
     "year": 2013 
     }, 
     { 
     "name": "X-Men: Days of Future Past", 
     "year": 2014 
     }, 
     { 
     "name": "Logan", 
     "year": 2017 
     }, 
    ] 
    } 
} 

Quelle serait la meilleure approche pour Décoder la partie data de la réponse? En outre, que se passe-t-il si le data est soudainement un array au lieu d'un objet, comment puis-je prendre en charge les deux types de données?

Merci beaucoup :)

+0

'Aussi, que se passe-t-il si les données sont soudainement un tableau au lieu d'un objet, comment puis-je prendre en charge les deux types de données?' - utiliser 'enum's avec associé valeurs dans votre type? Un cas avec 'array', autre avec' dictionary'. – user28434

+0

Vous devriez lire [Types personnalisés de codage et de décodage] (https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) dans la documentation Codable pour voir comment écrire des types qui reflètent votre représentation JSON. Généralement, cela implique d'écrire le type et de se conformer à Codable, et le reste devrait être fait pour vous. –

Répondre

0

D'abord, vous pouvez créer une extension en tant qu'aide:

extension Data { 
    func decode <Generic: Codable>() -> Generic? { 
     let decoder = JSONDecoder() 
     let object = try? decoder.decode(Generic.self, from: self) 
     return object 
    } 
} 


extension Dictionary { 
    func decode <Generic: Codable>() -> Generic? { 
     let data = try? JSONSerialization.data(withJSONObject: self, 
               options: JSONSerialization.WritingOptions.prettyPrinted) 
     guard let d = data else { 
      return nil 
     } 
     return d.decode() 
    } 
} 

Ensuite, vous pouvez créer un protocole pour vous aider à construire vos objets:

protocol Encode: Codable { 
    init(with dictionary: [String: Any]) 
    init(with data: Data) 
} 

avec une implémentation par défaut:

extension Encode { 
    init(with data: Data) { 
     let object: Self? = data.decode() 
     guard let obj = object else { 
      fatalError("fail to init object with \(data)") 
     } 
     self = obj 
    } 

    init(with dictionary: [String: Any]) { 
     let object: Self? = dictionary.decode() 
     guard let obj = object else { 
      fatalError("fail to init object with \(dictionary)") 
     } 
     self = obj 
    } 

Créez ensuite vos objets en tant que structure conforme au protocole y Codable. Il ressemblera:

struct User: Codable { 
    var name: String? 
    var nickname: String? 
    ... 
    // If needed declare CodingKey here 
    // enum CodingKeys: String, CodingKey { 
    //  case date = "dateOfBirth" 
    //  ... 
    // } 
} 

struct Movies: Codable { 
    var name: String? 
    var year: Int? 
} 

Maintenant, vous devez extraire votre dictionnaire de données de votre réponse et pour appliquer de nouvelles méthodes Init:

if let dic = json["data"] as? [String: Any] { 
    let user: User = User(with: dic) 
    // Do stuff here 
} 

Si les données deviennent soudainement un tableau, vous devrez le gérer différemment (comme un tableau d'utilisateur dans cet exemple)

+0

S'il vous plaît expliquer dans le commentaire pourquoi ma réponse n'est pas appropriée afin que je puisse le remplacer ou l'améliorer. Merci –

+0

Je n'ai aucune idée de qui a downvoted votre réponse, mais ce n'était pas moi. Je vais le lire demain matin et l'essayer. Je vais vous laisser savoir comment ça s'est passé :) – EpicSyntax