Freddy is a JSON parsing library maintained by Big Nerd Ranch. It has three principal benefits:
Type Safety: Helps you work with sending and receiving JSON in a way that prevents runtime crashes.
Idiomatic: Takes advantage of Swift's generics, enumerations, and functional features, without complicated documentation or magical custom operators.
Error Handling: Provides informative error information for commonly occurring JSON errors.
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)!
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 }
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 }
Any JSON
value can be serialized directly to NSData
.
let success = JSON.Bool(false) let data: NSData = try success.serialize()
Any model class that implements the JSONEncodable
protocol can be serialized directly to NSData
.
extension Person: JSONEncodable { public func toJSON() -> JSON { return .Dictionary([ "name": .String(name), "age": .Int(age), "spouse": .Bool(spouse) ]) } } let newPerson = Person(name: "Glenn", age: 23, spouse: true) let data: NSData = try newPerson.toJSON().serialize()