Freddy is a JSON parsing library maintained by Big Nerd Ranch. It has three principal benefits:

  1. Type Safety: Helps you work with sending and receiving JSON in a way that prevents runtime crashes.
  2. Idiomatic: Takes advantage of Swift’s generics, enumerations, and functional features, without complicated documentation or magical custom operators.
  3. Error Handling: Provides informative error information for commonly occurring JSON errors.

Example JSON Data

Let’s define some example JSON data for use with these examples.

{"success": true,"people": [{"name": "Matt Mathias","age": 32,"spouse": true},{"name": "Sergeant Pepper","age": 25,"spouse": false}],"jobs": ["teacher","judge"],"states": {"Georgia": [30301,30302,30303],"Wisconsin": [53000,53001]}}
let jsonString = "{\\"success\\": true, \\"people\\": [{\\"name\\": \\"Matt Mathias\\",\\"age\\": 32,\\"spouse\\": true},{\\"name\\": \\"Sergeant Pepper\\",\\"age\\": 25,\\"spouse\\": false}],\\"jobs\\": [\\"teacher\\",\\"judge\\"],\\"states\\": {\\"Georgia\\": [30301,30302,30303],\\"Wisconsin\\": [53000,53001]}}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!

Deserializing Raw Data

To deserialize the data, we initialize a JSON object then access a particular key.

do {
    let json = try JSON(data: jsonData)
    let success = try json.bool("success")
} catch {
    // do something with the error
}

We try here because accessing the json for the key "success" could fail–it might not exist, or the value might not be a boolean.

We can also specify a path to access elements nested in the JSON structure. The path is a comma-separated list of keys and indices that describe the path to a value of interest.

do {
    let json = try JSON(data: jsonData)
    let georgiaZipCodes = try json.array("states", "Georgia")
    let firstPersonName = try json.string("people", 0, "name")
} catch {
    // do something with the error
}

Deserializing Models Directly

JSON can be directly parsed to a model class that implements the JSONDecodable protocol.

public struct Person {
    public let name: String
    public let age: Int
    public let spouse: Bool
}

extension Person: JSONDecodable {
    public init(json: JSON) throws {
        name = try json.string("name")
        age = try json.int("age")
        spouse = try json.bool("spouse")
    }
}

do {
    let json = try JSON(data: jsonData)
    let people = try json.arrayOf("people", type: Person.self)
} catch {
    // do something with the error
}

Serializing Raw Data

Any JSON value can be serialized directly to NSData.

let success = JSON.Bool(false)
let data: NSData = try success.serialize()