Almazini
Almazini

Reputation: 1873

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?

Upvotes: 0

Views: 509

Answers (2)

Eric Aya
Eric Aya

Reputation: 70113

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

Upvotes: 2

nhgrif
nhgrif

Reputation: 62062

Seems like there are two problems:

  1. You're trying to use println to debug instead of setting a breakpoint and checking your objects values.
  2. You have not created a description or debugDescription property for your object, so println on your object is just using some default implementation.

shots is an array of your custom object, so when you call println, it's using the description for Array, which prints out the objects in the array, comma separated, and within square brackets.

The default description property for classes in Swift just prints the class name.

Ideally, you should just use a break point to check the values of your object to be certain it initialized correctly, but if it's actually important to get them to print right, it's only a matter of implementing the description property:

override var description: String {
    get {
        // build and return some string that represents your Shot object
    } 
}

Upvotes: 0

Related Questions