12

I have a response model that looks like this:

class ResponseModel: Mappable {

    var data: T?
    var code: Int = 0

    required init?(map: Map) {}

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

If the json-data is not an array it works:

{"code":0,"data":{"id":"2","name":"XXX"}}

but if it is an array, it does not work

{"code":0,"data":[{"id":"2","name":"XXX"},{"id":"3","name":"YYY"}]}

My mapping code;

let apiResponse = Mapper<ResponseModel>().map(JSONObject: response.result.value)

For details; I tried this code using this article : http://oramind.com/rest-client-in-swift-with-promises/

6 Answers 6

15

you need to use mapArray method instead of map :

let apiResponse = Mapper<ResponseModel>().mapArray(JSONObject: response.result.value)
Sign up to request clarification or add additional context in comments.

Comments

4

What I do is something like this:

func mapping(map: Map) {
    if let _ = try? map.value("data") as [Data] {
       dataArray <- map["data"]
    } else {
       data <- map["data"]
    }

    code <- map["code"]
}

where:

var data: T?
var dataArray: [T]?
var code: Int = 0

The problem with this is that you need to check both data and dataArray for nil values.

Comments

3

You need to change your declaration of data to an array, since that's how it is in the JSON:

var data: [T]? 

3 Comments

but data sometimes object sometimes array. is there a way for both?
Create two separate mappable classes, one for an array and one without an array. Try mapping the first one and if it fails try the second one.
Also, the API should really wrap the object in an array object even when there is only one element.
1
let apiResponse = Mapper<ResponseModel>().mapArray(JSONObject: response.result.value)

works for me

Comments

0

Anyone using SwiftyJSON and if you want an object from JSON directly without having a parent class, for example, you want the "data" from it. You can do something like this,

if let data = response.result.value {
   let json = JSON(data)
   let dataResponse = json["data"].object
   let responseObject = Mapper<DataClassName>().mapArray(JSONObject: dataResponse)
}

This will return you [DataClassName]? as response.

Comments

0

Based on Abrahanfer's answer. I share my solution. I wrote a BaseResult for Alamofire.

class BaseResult<T: Mappable> : Mappable {

var Result : Bool = false
var Error : ErrorResult?
var Index : Int = 0
var Size : Int = 0
var Count : Int = 0
var Data : T?
var DataArray: [T]?

required init?(map: Map){

}

func mapping(map: Map) {
    Result  <- map["Result"]
    Error <- map["Error"]
    Index <- map["Index"]
    Size <- map["Size"]
    Count <- map["Count"]

    if let _ = try? map.value("Data") as [T] {
       DataArray <- map["Data"]
    } else {
       Data <- map["Data"]
    }
}}

The usage for Alamofire :

WebService.shared.request(url, params, encoding: URLEncoding.default, success: { (response : BaseResult<TypeData>) in

            if let arr = response.DataArray
            {
                for year in arr
                {
                   self.years.append(year)
                }
            }
        }, failure: {

        })

The request method is :

 func request<T: Mappable>(_ url: String,_ parameters: [String : Any] = [:], _ method: HTTPMethod = .post,_ httpHeaders: HTTPHeaders? = nil, encoding: ParameterEncoding = JSONEncoding.default, success: @escaping (T) -> Void, failure: @escaping () -> () ) {

    AF.request(newUrl, method:method, parameters:parameters, encoding:encoding, headers: httpHeaders)

    .responseJSON { response in

        if let res = response.value {
            let json = res as! [String: Any]
            if let object = Mapper<T>().map(JSON: json) {
                success(object)
                return
            }
        }else if let _ = response.error {
            failure()
        }
    }
}

And TypeData class is :

class TypeData : Mappable
{
var Id : String = ""
var Title: String =  ""

required init(map: Map){

}

func mapping(map: Map) {
    Id  <- map["ID"]
    Title  <- map["YEAR"]
}}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.