Comment convertir un objet Swift en un dictionnaire

je suis relativement nouveau dans la programmation iOS. Cependant, J'aurais supposé que Swift aurait une façon automatisée de convertir des objets en JSON et vice versa. Cela étant dit, j'ai trouvé plusieurs bibliothèques qui peuvent le faire.

cependant...

il semble que peu importe comment vous postez des données à un service web (même en utilisant quelque chose comme AlamoFire), les demandes doivent être un dictionnaire. Tous ces forums montrent des exemples de la facilité avec laquelle il est possible de convertir la chaîne JSON retournée en objet. Vrai. Mais la requête doit être codée manuellement. C'est, passer par toutes les propriétés de l'objet et de la carte comme un dictionnaire.

alors ma question Est la suivante: est-ce que je manque quelque chose? Est-ce que j'ai tout faux et il y a un moyen super-facile pour (A) Envoyer JSON (au lieu d'un dictionnaire) dans la demande ou (b) convertir un objet automatiquement à un dictionnaire?

encore une fois, je vois combien il est facile de gérer une réponse JSON. Je cherche juste un moyen automatique de convertissez l'objet request que je veux poster dans un service web dans un format requis par une bibliothèque comme AlamoFire (ou autre). Avec D'autres langues, c'est assez banal, donc J'espère qu'il y a une manière aussi simple et automatisée avec Swift.

23
demandé sur JL Gradley 2015-08-12 19:58:03

4 réponses

actuellement Swift ne supporte pas la réflexion avancée comme Java ou C# donc la réponse est: non, il n'y a pas de manière aussi simple et automatisée avec Swift pur.

[Update] Swift 4 A entre-temps le Codable protocole qui permet de sérialiser vers / depuis JSON et PLIST.

typealias Codable = Decodable & Encodable
7
répondu Darko 2018-01-10 10:31:42

je suis en désaccord avec @Darko.

Swift 2,

utiliser programmation axée sur le protocole et la simple réflexion offerte par Miroir catégorie :

protocol JSONAble {}

extension JSONAble {
    func toDict() -> [String:Any] {
        var dict = [String:Any]()
        let otherSelf = Mirror(reflecting: self)
        for child in otherSelf.children {
            if let key = child.label {
                dict[key] = child.value
            }
        }
        return dict
    }
}

alors vous pouvez utiliser ce protocole avec votre classe de requête et produire le dictionnaire désiré:

class JsonRequest : JSONAble {
    var param1 : String?
    // ...
}

let request = JsonRequest()
// set params of the request
let dict = request.toDict()
// use your dict
41
répondu fencingCode 2015-09-20 18:00:28

sans utiliser la réflexion, et fonctionne pour les objets imbriqués (Swift 4):

protocol Serializable {
    var properties:Array<String> { get }
    func valueForKey(key: String) -> Any?
    func toDictionary() -> [String:Any]
}

extension Serializable {
    func toDictionary() -> [String:Any] {
        var dict:[String:Any] = [:]

        for prop in self.properties {
            if let val = self.valueForKey(key: prop) as? String {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Int {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Double {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Array<String> {
                dict[prop] = val
            } else if let val = self.valueForKey(key: prop) as? Serializable {
                dict[prop] = val.toDictionary()
            } else if let val = self.valueForKey(key: prop) as? Array<Serializable> {
                var arr = Array<[String:Any]>()

                for item in (val as Array<Serializable>) {
                    arr.append(item.toDictionary())
                }

                dict[prop] = arr
            }
        }

        return dict
    }
}

il suffit d'implémenter propriétés et valueForKey pour les objets personnalisés que vous voulez convertir. Par exemple:

class Question {
    let title:String
    let answer:Int

    init(title:String, answer:Int) {
        self.title = title
        self.answer = answer
    }
}
extension Question : Serializable {
    var properties: Array<String> {
        return ["title", "answer"]
    }

    func valueForKey(key: String) -> Any? {
        switch key {
        case "title":
            return title
        case "answer":
            return answer
        default:
            return nil
        }
    }
} 

vous pouvez ajouter plus de types de valeur dans la fonction toDictionary si vous avez besoin.

5
répondu Michael Eilers Smith 2017-07-29 15:11:50

vous pouvez aussi utiliser le ObjectMapper bibliothèque. Il a une méthode "toJSON" qui convertit votre objet en un dictionnaire.

3
répondu Remy Cilia 2017-01-17 08:08:31