Search code examples
arraysjsonswiftdictionarynsurlconnection

struggling with JSON parsing in swift


I am trying to load data in JSON format from my server into IOS application.

Here is my JSON:

[
  {
    "BankName": "bank1",
    "CurrencyName": "cur1",
    "SellRate": "0.65",
    "BuyRate": "0.55",
    "OfficialRate": "0.6"
  },
  {
    "BankName": "bank1",
    "CurrencyName": "cur2",
    "SellRate": "1.65",
    "BuyRate": "1.55",
    "OfficialRate": "1.6"
  }
]

There are 2 files in my project:

1:

import Foundation
class Shot {
    var bankName: String!
    var currencyName: String!
    var sellRate: String!
    var buyRate: String!
    var offRate: String!

    init (data: NSDictionary) {          
        self.bankName = getStringFromJSON(data, key:"BankName")
        self.currencyName = getStringFromJSON(data, key:"CurrencyName")
        self.sellRate = getStringFromJSON(data, key:"SellRate")
        self.buyRate = getStringFromJSON(data, key:"BuyRate")
        self.offRate = getStringFromJSON(data, key: "OfficialRate")
    }

    func getStringFromJSON(data: NSDictionary, key: String) -> String {                    
        if let info = data[key] as? String{
            return info
        }
        return ""
    }
}

2:

import Foundation
class JsonTest {    
    func loadJson(completion: ((AnyObject) -> Void)!) {    
        var urlString = "http://a.com/g.php"        
        let session = NSURLSession.sharedSession()
        let sourceUrl = NSURL(string: urlString)

        var task = session.dataTaskWithURL(sourceUrl!){
            (data, response, error) -> Void in

            if error != nil {
               println(error.localizedDescription)
            } else {

                var error: NSError?
                var jsonData = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &error) as NSArray

                var shots = [Shot]()

                println(jsonData)

                for shot in jsonData{
                    let shot = Shot(data: shot as NSDictionary)
                    shots.append(shot)                    
                }                
                println(shots)   //[jsontest.Shot, jsontest.Shot]                
            }
        }        
        task.resume()
    }
}

I am trying to populate array automatically when my app starts. To do it I have a code in my mainViewController class.

override func viewDidLoad() {
    super.viewDidLoad()

   let api = JsonTest()
    api.loadJson(nil)

}

The problem occurs when I try to print shots variable in the second file. it returns [jsontest.Shot, jsontest.Shot] when I was expecting the array of dictionaries.

println(jsonData) works fine and shows JSON data from URL.

Can anybody advise what is wrong in my program?


Solution

  • "shots" is an array of instances of Shot, not a dictionary:

    class Shot {
        var bankName: String!
        var currencyName: String!
        var sellRate: String!
        var buyRate: String!
        var offRate: String!
    
        init (data: NSDictionary) {
            self.bankName = getStringFromJSON(data, key:"BankName")
            self.currencyName = getStringFromJSON(data, key:"CurrencyName")
            self.sellRate = getStringFromJSON(data, key:"SellRate")
            self.buyRate = getStringFromJSON(data, key:"BuyRate")
            self.offRate = getStringFromJSON(data, key: "OfficialRate")
        }
    
        func getStringFromJSON(data: NSDictionary, key: String) -> String {
            if let info = data[key] as? String{
                return info
            }
            return ""
        }
    }
    
    var shots = [Shot]()
    let urlString = "http://almazini.lt/getrates.php"
    let sourceUrl = NSURL(string: urlString)
    // Using NSData instead of NSURLSession for experimenting in Playground
    let data = NSData(contentsOfURL: sourceUrl!)
    var error: NSError?
    // As I'm using Swift 1.2 I had to change "as" with "as!"
    let jsonData = NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers, error: &error) as! NSArray
    for shot in jsonData{
        let shot = Shot(data: shot as! NSDictionary)
        shots.append(shot)
    }
    println(shots[0].bankName)
    

    screenshot

    Update for Swift 2

    var shots = [Shot]()
    let urlString = "http://almazini.lt/getrates.php"
    // Using NSData instead of NSURLSession for experimenting in Playground
    if let sourceUrl = NSURL(string: urlString) {
        NSURLSession.sharedSession().dataTaskWithURL(sourceUrl, completionHandler: { (data, response, error) in
            if error == nil {
                if let data = data, jsonData = try? NSJSONSerialization.JSONObjectWithData(data, options: []), jsonArray = jsonData as? [NSDictionary] {
                    for item in jsonArray {
                        let shot = Shot(data: item)
                        shots.append(shot)
                    }
                    print(shots[0].bankName)
                } else {
                    print("no JSON data")
                }
            } else {
                print(error!.localizedDescription)
            }
        }).resume()
    }