Search code examples
jsonswift3alamofireobjectmapper

AlamofireObjectMapper in swift 3


I want to use AlamofireObjectMapper for the first time to parse a json response in swift.

The response is:

  "success": true,
  "terms": "https:\/\/currencylayer.com\/terms",
  "privacy": "https:\/\/currencylayer.com\/privacy",
  "timestamp": 1480007048,
  "source": "USD",
  "quotes": {
    "USDAED": 3.672598,
    "USDAFN": 66.599998,
    "USDALL": 127.999937,
    "USDAMD": 478.679993,
    "USDANG": 1.780277,
    "USDAOA": 165.072998,
    "USDARS": 15.497261,
    "USDAUD": 1.348899,
    "USDAWG": 1.79,
    "USDAZN": 1.714104,
    "USDBAM": 1.855297,
    "USDBBD": 2,
    "USDBDT": 79.179735,
    "USDBGN": 1.854199,
    "USDBHD": 0.377036,
    "USDBIF": 1668.300049,
    "USDBMD": 1,
    "USDBND": 1.429902,
    "USDBOB": 6.870014,
    "USDBRL": 3.396898,
    "USDBSD": 1,
}

I mapped it like this:

class ModelCurrency:  Mappable {

    var success   : Bool?
    var terms     : String?
    var privacy   : String?
    var timestamp : CGFloat?
    var source    : String?
    var quotes    : [Quotes]?

    init() {}

    required init?(map: Map) {

    }

    func mapping(map: Map) {

         success<-map["success"]
         terms<-map["terms"]
         privacy<-map["privacy"]
         timestamp<-map["timestamp"]
         source<-map["source"]
         quotes<-map["quotes"]

        print("It json\(terms)")
    }
}

class Quotes : Mappable {

    var name : String?
    var val : CGFloat?

    required init?(map: Map) {

    }

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

And in my controller:

 override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        super.viewDidLoad()
        let URL = "http://www.apilayer.net/api/live?access_key=ad847a0a855c0647590df2b818923025"

 Alamofire.request(URL).responseArray(queue: "quotes") { (response: DataResponse<[Quotes]>) in
            let arrayCurency = response.result.value!


                for quotes in arrayCurency {
                    print(quotes.name!)
                    print(quotes.val!)
                }

        }

    }

It gives me error mapping and this error:

cannot convert value 'String' to expected argument type 'DispatchQueue?'

enter image description here


Solution

  • There are several issues.

    1. You want to reference DataResponse<ModelCurrency> rather than DataResponse<[Quotes]>.

    2. You want to use responseObject, not responseArray.

    3. You don't want to use that queue parameter with a String value. The queue parameter is used to specify which dispatch queue you want the completion handlers to run. But that's not what you're doing here, so you should just remove it.

    4. The value associated with the quotes key is not an array of objects. It is yet another dictionary. So you should map it to a dictionary, and then use map method to convert that to an array of Quote objects.

    So, pulling that all together:

    Alamofire.request(urlString).responseObject { (response: DataResponse<ModelCurrency>) in
        ...
    }
    

    And

    class ModelCurrency:  Mappable {
    
        var success   : Bool?
        var terms     : String?
        var privacy   : String?
        var timestamp : CGFloat?
        var source    : String?
        var quotes    : [Quote]?
    
        required init?(map: Map) { }
    
        func mapping(map: Map) {
    
            success    <- map["success"]
            terms      <- map["terms"]
            privacy    <- map["privacy"]
            timestamp  <- map["timestamp"]
            source     <- map["source"]
    
            var dictionary: [String: CGFloat]?
            dictionary <- map["quotes"]
            quotes = dictionary?.map { return Quote(name: $0.key, val: $0.value) }
        }
    }
    
    class Quote {
    
        var name : String?
        var val : CGFloat?
    
        init(name: String?, val: CGFloat?) {
            self.name = name
            self.val  = val
        }
    
    }
    

    (I've renamed Quotes to Quote as it would appear to be a quote for a single currency.)