Tarvo Mäesepp Tarvo Mäesepp - 4 months ago 8
Swift Question

nil while parsing JSON in Swift

I am doing some easy projects to learn new things. I started parsing

JSON
with
SwiftyJSON
. I am trying to show some
JSON
data to the
tableView
but now I am stuck. I do not know where is the nil and why. Can you help me guys? In given code I am trying to get the
"Brands"
and show them inside
tableView
or at least print those into
console
.

This is the
.json
file I have:

{
"Snuses": {
"Brands":{


"CATCH": [
{"Products":"white", "nicotine":"8.0"},
{"Products":"yellow", "nicotine":"8.0"}
],
"GENERAL": [
{"Products":"brown", "nicotine":"8.0"},
{"Products":"white", "nicotine":"8.0"}
]
}
}
}


And here I try to get the info like this:

var numberOfRows = 0

var snusBrandsArray = [String]()

override func viewDidLoad() {
super.viewDidLoad()
parseJSON()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()

}

func parseJSON(){
let path: String = NSBundle.mainBundle().pathForResource("snuses", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data: jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)

var brands = readableJSON["Snuses", "Brands"]

NSLog("\(brands)")

numberOfRows = readableJSON["Snuses"].count

for i in 1...numberOfRows{
var brands = "Snuses"
brands += "\(i)"
var name = readableJSON["Snuses", "Brands"].string as String!
snusBrandsArray.append(name)
}
}

Answer

What about something simple, like this? Below is Playground code but the parsing is the same.

//: Playground

import UIKit
import Foundation

var jsonStr = "{ \"Snuses\": { \"Brands\":{ \"CATCH\": [ {\"Products\":\"white\", \"nicotine\":\"8.0\"}, {\"Products\":\"yellow\", \"nicotine\":\"8.0\"} ], \"GENERAL\": [ {\"Products\":\"brown\", \"nicotine\":\"8.0\"}, {\"Products\":\"white\", \"nicotine\":\"8.0\"} ] } } }"

func parseJSON(jsonStr:String) throws -> [AnyObject]? {

    var brandNameKeys:[AnyObject]?
    let jsonData = jsonStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

    let json = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions())

    if let brandNameDict = json["Snuses"]!?["Brands"] as? NSDictionary
    {
        brandNameKeys = brandNameDict.allKeys
    }

   return brandNameKeys
}

if let result = try parseJSON(jsonStr)
{
    print(result)
}

In my Playground this outputs ["CATCH", "GENERAL"] which I think is what you want.

Here's a full UITableViewController demonstrating the solution in use:

import UIKit

class TableViewController: UITableViewController {

    var data:[AnyObject]?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let path: String = NSBundle.mainBundle().pathForResource("Data", ofType: "json")
        {
            do
            {
                let jsonStr = try String(contentsOfFile: path)
                data = try parseJSONStr(jsonStr)
            }
            catch _ {
                print("Loading json failed")
            }
        }
    }


    // JSON Parsing
    func parseJSONStr(jsonStr:String) throws -> [AnyObject]? {

        var brandNameKeys:[AnyObject]?
        let jsonData = jsonStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

        let json = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions())

        if let brandNameDict = json["Snuses"]!?["Brands"] as? NSDictionary
        {
            brandNameKeys = brandNameDict.allKeys
        }

        return brandNameKeys
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let data = data
        {
            return data.count
        }
        else
        {
            return 0
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("SampleCell", forIndexPath: indexPath)

        if let rowData = data![indexPath.row] as? String
        {
             cell.textLabel?.text = rowData
        }

        return cell
    }
}