J'utilise la bibliothèque ObjectMapper pour mapper json avec mes objets mais j'ai quelques problèmes pour mapper un tableau json racine.
C'est le json reçu:
[
{
CustomerId = "A000015",
...
},
{
CustomerId = "A000016",
...
},
{
CustomerId = "A000017",
...
}
]
C'est mon objet
class Customer : Mappable
{
var CustomerId : String? = nil
class func newInstance(map: Map) -> Mappable? {
return Customer()
}
func mapping(map: Map) {
CustomerId <- map["CustomerId"]
}
}
Je mappe le json dans mon contrôleur avec
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSArray
if (error != nil) {
return completionHandler(nil, error)
} else {
var customers = Mapper<Customer>().map(json)
}
Mais ça ne marche pas, j'ai essayé Mapper<[Customer]>().map(json)
mais ça ne marche pas aussi. Enfin, j'ai essayé de créer un nouvel objet Swift CustomerList contenant un tableau Customer mais cela ne fonctionne pas.
Avez-vous une idée de la façon de mapper json d'un tableau racine?
Merci.
Je résous enfin mon problème:
La méthode de mappage dans le contrôleur doit être
let json : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
if (error != nil) {
return completionHandler(nil, error)
} else {
var customer = Mapper<Customer>().mapArray(json)! //Swift 2
var customer = Mapper<Customer>().mapArray(JSONArray: json)! //Swift 3
}
Si cela peut aider quelqu'un.
JSONObjectWithData(::)
avec le type de conversion descendante conditionnelle correctVotre JSON est de type [[String: AnyObject]]
. Par conséquent, avec Swift 2, vous pouvez utiliser JSONObjectWithData(::)
avec une conversion descendante conditionnelle de type [[String: AnyObject]]
Afin d'éviter d'utiliser NSArray
ou AnyObject!
:
do {
if let jsonArray = try NSJSONSerialization
.JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
/* perform your ObjectMapper's mapping operation here */
} else {
/* ... */
}
}
catch let error as NSError {
print(error)
}
Customer
à l'aide de la méthode mapArray(:)
La classe ObjectMapper
de Mapper
fournit une méthode appelée mapArray(:)
qui a la déclaration suivante:
public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?
La documentation ObjectMapper
indique à ce sujet:
Mappe un tableau de dictionnaire JSON à un tableau d'objets mappables
Ainsi, votre code final devrait ressembler à ceci:
do {
if let jsonArray = try NSJSONSerialization
.JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
let customerArray = Mapper<Customer>().mapArray(jsonArray)
print(customerArray) // customerArray is of type [Customer]?
} else {
/* ... */
}
}
catch let error as NSError {
print(error)
}
Customer
à l'aide de la méthode map(:)
La classe ObjectMapper
de Mapper
fournit une méthode appelée map(:)
qui a la déclaration suivante:
func map(JSONDictionary: [String : AnyObject]) -> N?
La documentation ObjectMapper
indique à ce sujet:
Mappe un dictionnaire JSON à un objet conforme à Mappable
Comme alternative au code précédent, le code suivant montre comment mapper votre JSON à Customer
à l'aide de map(:)
:
do {
if let jsonArray = try NSJSONSerialization
.JSONObjectWithData(data, options: []) as? [[String: AnyObject]] {
for element in jsonArray {
let customer = Mapper<Customer>().map(element)
print(customer) // customer is of type Customer?
}
} else {
/* ... */
}
}
catch let error as NSError {
print(error)
}
La solution la plus simple est fournie par AlamofireObjectMapper . Utilisez la méthode de commodité responseArray()
:
Alamofire.request(endpoint).responseArray { (response: DataResponse<[MyMappableClass]>) in
if let result = response.result.value {
// Customer array is here
} else if let error = response.result.error {
// Handle error
} else {
// Handle some other not networking error
}
}
Dans la même situation dans mon récent Swift 3, capable de résoudre pour obtenir le mappeur d'objets présent dans Array en tant que root.
Convertissez d'abord la chaîne json en objet à l'aide de la sérialisation.
let parsedMapperString = Mapper<Customer>.parseJSONString(JSONString: result) //result is string from json serializer
Ensuite, vous pouvez obtenir le DTO client du dictionnaire MapSet of JSON vers un tableau d'objets mappables.
let customerDto = Mapper<Customer>().mapSet(JSONArray: jsonParsed as! [[String : Any]])
J'espère que ça aide. Merci à @Nicolas qui m'a poussé près pour trouver une solution.
Convertissez le tableau en json et vice-versa:
let json = shops.toJSONString()
let shops = Array<Shop>(JSONString: json)
Un bon moyen de résoudre le problème de mappage d'un tableau racine avec un objet générique consiste à créer un objet générique qui crée une liste avec l'objet à l'intérieur de l'implémentation de classe. Voyons un exemple de ce type d'implémentation ci-dessous:
Alamofire.request(REQ_URL_STRING,
method: REQ_METHOD(eg.: .GET),
parameters: REQ_PARAMS,
encoding: REQ_ENCODING,
headers: REQ_HEADERS).responseObject { (response: DataResponse<GenericResponseList<SingleElement>>) in
//your code after serialization here
}
Dans le code ci-dessus, vous remplissez les variables majuscules avec vos propres valeurs. Vérifiez que le retour de réponse dans la fermeture est un objet générique DataResponse d'Alamofire, et j'en ai créé un autre appelé GenericResponseList. Je mets à l'intérieur du "<>" le type de l'objet que je vais obtenir une liste du serveur. Dans mon cas, c'était une liste de SingleElements.
Maintenant, jetez un œil à l'implémentation de GenericResponseList ci-dessous:
final class GenericResponseList<T: Mappable>: Mappable {
var result: [T]?
required convenience init?(map: Map) {
self.init()
}
func mapping(map: Map) {
result <- map["result"]
}
}
Jetez un oeil, j'ai une variable à l'intérieur de la classe qui est une liste du type générique que j'ai envoyé à cette classe.
var result: [T]?
Alors maintenant, lorsque vous obtenez votre JSON, il le convertira en une liste de SingleElement.
J'espère que cela a aidé :)