Search code examples
jsonswiftparsingnsdictionary

How parse a json data that has a dictionary key:value pair? I'm trying to extract the symbol and value pair


How to correctly parse the following json data? My problem is at the line: if let rates = data["rates"] as? NSDictionary...

The json data

{   "valid": true,   
    "timestamp": 1579683079,   
    "base": "USD",  
    "rates": {
       "AED": 3.67316,
       "AFN": 77.99911,
       "ALL": 110.11741,
       ...
       "ZAR": 14.45,
       "ZMW": 14.63257   
     } 
 }

Code

import UIKit

struct CurrencyRate {
    var valid: String
    var timestamp: Int
    var base: String
    var rates: [String:Double] = [:]
}

class ViewController: UIViewController {

var mySymbols:[String] = []
var myValues:[Double] = []


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    let jsonUrlString = "https://currencyapi.net/api/v1/rates?key=6b171cc58787d922eb53e3684d97784d165a&base=USD"

    guard let url = URL(string: jsonUrlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data else { return }

        //let dataAsString = String(data: data, encoding: .utf8)
        if let rates = data["rates"] as? NSDictionary {
            for (key, value) in rates {
                self.mySymbols.append((key as? String)!)

                self.myValues.append((value as? Double)!)
            }
        }


    }.resume()

}

}

Solution

  • Don't use NSDictionary - use Dictionary type in Swift. Also, you have data and it's not dictionary at all. It's Data type. Use should convert your data to your type. Try use this code:

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data else { return }
    
        let jsonResult = try? JSONSerialization.jsonObject(with: data)
    
        if let dict = jsonResult as? Dictionary<String, Any>, let rates = dict["rates"] as? Dictionary<String, Double> {
            for (key, value) in rates {
                print(key, value)
                self.mySymbols.append(key)
                self.myValues.append(value)
            }
        }
    }.resume()
    

    There is a way with Codable, but I guess it will be the next challenge for you. Also, keep in mind that the code is executed asynchronously and the data in global variables will not appear immediately