JSON and Xcode (iOS): The Swift Basics




Note: there is now a library called Aldwych on GitHub that handles JSON in Swift, and which I would highly recommend you take a look at. It solves the issues found here. (Disclaimer: I created the  library.)



A while ago, I wrote a post called JSON and Xcode (iOS): The Basics. This post is an extension to that one and supplies an example of how to do the same thing as before but this time in Swift.

Loading JSON and converting to Swift objects


// Create filepath
var filepath:String = NSBundle.mainBundle().pathForResource("hello", ofType: "json")
// Create optional for NSError

var error:NSError?

// Retrieve Data
var JSONData = NSData.dataWithContentsOfFile(filepath, options: NSDataReadingOptions.DataReadingMapped, error:&error)
// Create another error optional
var jsonerror:NSError?
// We don't know the type of object we'll receive back so use AnyObject
let swiftObject:AnyObject = NSJSONSerialization.JSONObjectWithData(JSONData, options: NSJSONReadingOptions.AllowFragments, error:&jsonerror)
// JSONObjectWithData returns AnyObject so the first thing to do is to downcast this to a known type
if let nsDictionaryObject = swiftObject as? NSDictionary {
    if let swiftDictionary = nsDictionaryObject as Dictionary? {
        println(swiftDictionary)
    }
}
else if let nsArrayObject = swiftObject as? NSArray {
    if let swiftArray = nsArrayObject as Array? {
        println(swiftArray)
    }
}

Creating JSON from Swift objects

Going the other way and creating JSON, we would do this:

var jsonCreationError:NSError?
var jsonArray = [["one":"two"],"buckle",["my","shoe"]]
let json:NSData = NSJSONSerialization.dataWithJSONObject(jsonArray, options: NSJSONWritingOptions.PrettyPrinted, error: &jsonCreationError)
if jsonCreationError {
    println("Errors: \(jsonCreationError)")
}
else {
    // everything is fine and we have our json stored as an NSData object
}

The problem with this approach

NSJSONSerialization.JSONObjectWithData returns only NSArray, NSDictionary, NSNumber, NSString, and NSNull objects, and while we can downcast objects, this does not downcast the contents of the array or dictionary. This means that where we have a complex piece of JSON where a dictionary or array contains not only strings and numbers but further dictionaries and arrays, these dictionaries and arrays are not automatically downcast as well, they remain NSArray and NSDictionary objects. 

This creates challenges when dealing with JSON in Swift. Do we create our class to enumerate over the JSON and transform it into native Swift objects? Do we turn to someone else's work, like SwiftyJSON? Do we keep working as we did in Objective-C with the Cocoa Touch Framework? Or do we wait and see if Apple makes changes in later releases of Swift?

If we look to Windows and Android frameworks, then we see that they have specific JSON classes to work with the format. Will Apple do the same with Swift? Will they provide something better? Or, is JSON of the kind that contains many depths simply not in tune with the new language of strongly-typed objects?


Endorse on Coderwall

Comments