parser parse jsonserialization array ios json swift nsarray

ios - jsonserialization - parse json swift 4



iOS: mapee una matriz JSON raíz con ObjectMapper en forma rápida (6)

Uso la biblioteca ObjectMapper para mapear json con mis objetos, pero tengo algunos problemas para mapear una raíz json Array.

Este es el json recibido:

[ { CustomerId = "A000015", ... }, { CustomerId = "A000016", ... }, { CustomerId = "A000017", ... } ]

Este es mi objeto

class Customer : Mappable { var CustomerId : String? = nil class func newInstance(map: Map) -> Mappable? { return Customer() } func mapping(map: Map) { CustomerId <- map["CustomerId"] } }

Asigné el json en mi controlador con

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) }

Pero no funciona, probé Mapper<[Customer]>().map(json) pero tampoco funciona. Finalmente, traté de crear un nuevo CustomerList objeto rápido que contiene una matriz de cliente, pero no funciona.

¿Tiene una idea de cómo mapear json de una matriz raíz?

Gracias.


Usando JSONObjectWithData(::) con el tipo de JSONObjectWithData(::) condicional correcto

Su JSON es del tipo [[String: AnyObject]] . Por lo tanto, con Swift 2, puede usar JSONObjectWithData(::) con un JSONObjectWithData(::) condicional de tipo [[String: AnyObject]] para evitar el uso de NSArray o 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) }

Mapeo al Customer usando el método mapArray(:)

La clase Mapper ObjectMapper proporciona un método llamado mapArray(:) que tiene la siguiente declaración:

public func mapArray(JSONArray: [[String : AnyObject]]) -> [N]?

La documentación de ObjectMapper dice al respecto:

Mapas una matriz de diccionario JSON para una matriz de objetos Mappable

Por lo tanto, su código final debería verse más o menos así:

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) }

Mapeo al Customer usando el método map(:)

La clase Mapper ObjectMapper proporciona un método llamado map(:) que tiene la siguiente declaración:

func map(JSONDictionary: [String : AnyObject]) -> N?

La documentación de ObjectMapper dice al respecto:

Asigna un diccionario JSON a un objeto que se ajusta a Mappable

Como alternativa al código anterior, el siguiente código muestra cómo asignar su JSON al Customer usando el 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) }


Convierte array a json y viceversa:

let json = shops.toJSONString() let shops = Array<Shop>(JSONString: json)


En la misma situación en mi reciente Swift 3, soy capaz de resolver para obtener el mapeador de objetos presente en Matriz como raíz.

Primero convierta una cadena json en un objeto usando la serialización.

let parsedMapperString = Mapper<Customer>.parseJSONString(JSONString: result) //result is string from json serializer

Luego puede obtener Customer DTO del MapSet del diccionario JSON en una matriz de objetos Mappable.

let customerDto = Mapper<Customer>().mapSet(JSONArray: jsonParsed as! [[String : Any]])

Espero eso ayude. Gracias a @Nicolas que me presionó para obtener una solución.


Finalmente resuelvo mi problema:

El método de mapeo en el controlador debe ser

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 puede ayudar a alguien


La solución más fácil es provista por AlamofireObjectMapper . Use el método de conveniencia 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 } }


Una buena forma de resolver el problema de mapear una matriz raíz con un objeto genérico es crear un objeto genérico que cree una lista con el objeto dentro de la implementación de la clase. Veamos un ejemplo de este tipo de implementación a continuación:

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 }

En el código anterior, rellenará las variables en mayúscula con sus propios valores. Compruebe que el retorno de la respuesta en el cierre es un objeto genérico DataResponse de Alamofire, y creé otro llamado GenericResponseList. Puse en el interior el "<>" el tipo de objeto que obtendré una lista del servidor. En mi caso, era una lista de SingleElements.

Ahora, eche un vistazo a la implementación de GenericResponseList a continuación:

final class GenericResponseList<T: Mappable>: Mappable { var result: [T]? required convenience init?(map: Map) { self.init() } func mapping(map: Map) { result <- map["result"] } }

Eche un vistazo, tengo una variable dentro de la clase que es una lista del tipo genérico que envié a esta clase.

var result: [T]?

Entonces, cuando obtenga JSON, lo convertirá en una lista de SingleElement.

Espero que haya ayudado :)