/json-swift

A basic library for working with JSON in Swift.

Primary LanguageSwiftMIT LicenseMIT

json-swift

A lightweight library for working with JSON in Swift.

Why do we need it?

Suppose you receive the following JSON and need to extract blogs/blog/1/name:

{
    "stat": "ok",
    "blogs": {
        "blog": [
            {
                "id" : 73,
                "name" : "Bloxus test",
                "needspassword" : true,
                "url" : "http://remote.bloxus.com/"
            },
            {
                "id" : 74,
                "name" : "Manila Test",
                "needspassword" : false,
                "url" : "http://flickrtest1.userland.com/"
            }
        ]
    }
}

Swift is a type-safe language. It's usually fine, but in this case it can get you in the throat:

let json: AnyObject! = receiveSomeData()
if let name = ((((json as? NSDictionary)?["blogs"] as? NSDictionary)?["blog"]
              as? NSArray)?[1] as? NSDictionary)?["name"] as? NSString {
    // Finally, we can use the item.
} else {
    // Something went wrong. But what did?
}

It's a very verbose way to say we need that "Manila test". On the other side, json-swift provides a clean syntax for accessing items:

let json = JSONValue(receiveSomeData())
if let name = json["blogs"]["blog"][1]["name"].string {
    // Use the string.
} else {
    println(name.error!.localizedDescription)
}

Getting started

Getting JSON data

As shown before, we can create a JSONValue from nested NSDictionary and NSArray objects. We can also initialize it using an NSData or create inline JSON from Swift literals:

let json: JSONValue = [
    "stat": "ok",
    "blogs": [
        "blog": [
            [
                "id" : 73,
                "name" : "Bloxus test",
                "needspassword" : true,
                "url" : "http://remote.bloxus.com/"
            ],
            [
                "id" : 74,
                "name" : "Manila Test",
                "needspassword" : false,
                "url" : "http://flickrtest1.userland.com/"
            ]
        ]
    ]
]

Accessing items and browsing paths

Obtaining your actual JSON value consists of 2 steps. Firstly, you provide a path using subscript chain, as shown above. Then you call one of the type-casting properties: string, number (Double), integer, bool, array, object. They return an Optional containing the required type if it is correct, and nil otherwise.

Don't worry if the objects you are trying to access do not exist. The result of all the subscripts will contain NSError, which you can access with error property:

let urlNode = json["blogs"]["blog"][2]["url"]
if urlNode.hasValue {
    let urlString = urlNode.string!
} else {
    let error = urlNode.error!
    println(error.localizedMessage)
}

In the if condition we check if no error occurred. In case urlNode is not found, at least we will see where the error occurred. In this case the message will hint us that the error began at [2] subscript.

Modifying JSON tree

You can set any JSON node in the same manner you can access it. But make sure that the JSONValue is declared as a var, not let:

var modifyableJSON = json
modifyableJSON["stat"] = "fail"
assert(modifyableJSON["stat"].string! == "fail")

Note that Apple does not make any guarantee about the performance of such editing. The whole JSON subtree may be copied on each modification.

Installation

Clone the repository to your Workspace directory and add JSON.xcodeproj to the Workspace.

Contribution

Fork the repository, push your commits, then create a pull request.