Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - Map a root JSON array with ObjectMapper in swift

I use the library ObjectMapper to map json with my objects but I have some issues to map a root json Array.

This is the received json :

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

This is my object

class Customer : Mappable
{
    var CustomerId : String? = nil

    class func newInstance(map: Map) -> Mappable? {
        return Customer()
    }

    func mapping(map: Map) {
        CustomerId   <- map["CustomerId"]
    }
}

I map the json in my controller with

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

But it doesn't work, I tried Mapper<[Customer]>().map(json) but it doesn't work too. Finally I tried to create a new swift object CustomerList containing a Customer array but it doesn't work.

Do you have an idea of how to map json of a root array ?

Thanks.

like image 945
Nicolas HENAUX Avatar asked Sep 02 '15 12:09

Nicolas HENAUX


2 Answers

I finally solve my problem :

The mapping method in the controller should be

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
}

If it can help someone.

like image 128
Nicolas HENAUX Avatar answered Oct 14 '22 17:10

Nicolas HENAUX


Using JSONObjectWithData(::) with the correct conditional downcasting type

Your JSON is of type [[String: AnyObject]]. Therefore, with Swift 2, you can use JSONObjectWithData(::) with a conditional downcasting of type [[String: AnyObject]] in order to prevent using NSArray or 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)
}

Mapping to Customer using mapArray(:) method

The ObjectMapper's Mapper class provides a method called mapArray(:) that has the following declaration:

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

The ObjectMapper documentation states about it:

Maps an array of JSON dictionary to an array of Mappable objects

Thus, your final code should look something like this:

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

Mapping to Customer using map(:) method

The ObjectMapper's Mapper class provides a method called map(:) that has the following declaration:

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

The ObjectMapper documentation states about it:

Maps a JSON dictionary to an object that conforms to Mappable

As an alternative to the previous code, the following code shows how to map your JSON to Customer using 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)
}
like image 25
Imanou Petit Avatar answered Oct 14 '22 18:10

Imanou Petit