Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON String to NSDictionary with Swift

I am trying to create a dictionary from data that is held in a server, I receive the data but I cannot convert the data to an NSDictionary, I believe it is held in an NSData Object

let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData!, options: nil, error: &error) as NSDictionary

This line of code is the one giving me the problem, it throws a BAD_EXEC_INSTRUCTION.

MY Question: How can I turn a JSON into an NSDictionary?

like image 960
Arafal Avatar asked Mar 17 '15 05:03

Arafal


1 Answers

Your code does not do any error handling. But it can (and if this data comes from a web service, will) fail in multiple ways.

  1. You have to make sure that your data object actually exists
  2. You have to make sure that the data object can be converted to JSON
  3. You have to make sure that the JSON actually contains a Dictionary

You should use Swifts conditional cast and it's optional binding capabilities.
The optional binding if let JSONData = JSONData checks that JSONData is not nil. The force unwrap (JSONData!) you use might crash if no data could be received.

The optional binding if let json = NSJSONSerialization.JSONObjectWithData checks if the data could be converted to a JSON object. The conditional cast as? NSDictionary checks if the JSON object is actually a dictionary. You currently don't use these checks, you cast the objects as NSDictionary. Which will crash, if the object is not valid json, or if its not a dictionary.

I would recommend something like this:

var error: NSError?
if let JSONData = JSONData { // Check 1
    if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) { // Check 2
        if let jsonDictionary = json as? NSDictionary { // Check 3
            println("Dictionary received")
        }
        else {
            if let jsonString = NSString(data: JSONData, encoding: NSUTF8StringEncoding) {
                println("JSON String: \n\n \(jsonString)")
            }
            fatalError("JSON does not contain a dictionary \(json)")
        }
    }
    else {
        fatalError("Can't parse JSON \(error)")
    }
}
else {
    fatalError("JSONData is nil")
}

You could merge check 2 and 3 into one line and check if NSJSONSerialization can create a NSDictionary directly:

var error: NSError?
if let JSONData = JSONData { // Check 1.
    if let JSONDictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) as? NSDictionary { // Check 2. and 3.
        println("Dictionary received")
    }
    else {

        if let jsonString = NSString(data: JSONData, encoding: NSUTF8StringEncoding) {
            println("JSON: \n\n \(jsonString)")
        }
        fatalError("Can't parse JSON \(error)")
    }
}
else {
    fatalError("JSONData is nil")
}

Make sure to replace fatalError with appropriate error handling in your production code

like image 81
Matthias Bauch Avatar answered Sep 30 '22 14:09

Matthias Bauch