
Lightning fast JSON deserialization for iOS & OS X written in Swift. Expanded upon the ideas found in this blog post.
- Introduction
- Installation
- Operator List
- Simple Tutorial
- Assigning Default Values
- NSDate and NSURL Deserialization
- JSON String Deserialization
JSONHelper is a library written to make sure that deserializing data obtained from an API is as easy as possible. It doesn't depend on any networking libraries, and works equally well with any of them.
Requires iOS 7 or later and Xcode 6.1+
I plan to support CocoaPods when it starts working with Swift libraries. Until then, as a quick and easy (yet a bit dirty) method, I recommend directly adding JSONHelper.swift into your project.
Operator | Functionality |
---|---|
<<< | For deserializing data into primitive types, NSDate or NSURL. |
<<<* | For deserializing data into an array of primitive types, NSDate or NSURL. |
<<<< | For deserializing data into an instance of a class. Supports JSON strings |
<<<<* | For deserializing data into an array that contains instances of a certain class. Supports JSON strings |
Please take a good look at the operator list before you start reading this tutorial. Also, for simplicity, I'm going to assume you use AFNetworking as your networking library. Let's say we have an endpoint at http://yoursite.com/your-endpoint/ which gives the following response when a simple GET request is sent to it.
{
"books": [
{
"author": "Irvine Welsh",
"name": "Filth"
},
{
"author": "Bret Easton Ellis",
"name": "American Psycho"
}
]
}
From this response it is clear that we have a book model similar to the implementation below.
class Book {
var author: String?
var name: String?
}
We now have to make it extend the protocol Deserializable and implement the required init(data: [String: AnyObject]) initializer. The complete model should look like this:
class Book: Deserializable {
var author: String? // You can also use let instead of var if you want.
var name: String?
required init(data: [String: AnyObject]) {
author <<< data["author"]
name <<< data["name"]
}
}
And finally, requesting and deserializing the response from our endpoint becomes as easy as the following piece of code.
AFHTTPRequestOperationManager().GET(
"http://yoursite.com/your-endpoint/"
parameters: nil,
success: { operation, data in
var books: [Book]?
books <<<<* data["books"]
if let books = books {
// Response contained a books array, and we deserialized it. Do what you want here.
} else {
// Server gave us a response but there was no books key in it, so the books variable
// is equal to nil. Do some error handling here.
}
},
failure: { operation, error in
// Handle error.
})
You can easily assign default values to variables in cases where you want them to have a certain value when deserialization fails.
class User: Deserializable {
var name = "Guest"
required init(data: [String: AnyObject]) {
name <<< data["name"]
}
}
The <<< and <<<* operators also support deserializing data into NSDate and NSURL variables.
let website: NSURL?
let imageURLs: [NSURL]?
website <<< "http://mywebsite.com"
imageURLs <<<* ["http://mywebsite.com/image.png", "http://mywebsite.com/anotherImage.png"]
let meetingDate: NSDate?
let partyDates: [NSDate]?
meetingDate <<< (value: "2014-09-18", format: "yyyy-MM-dd")
partyDates <<<* (value: ["2014-09-19", "2014-09-20"], format: "yyyy-MM-dd")
let myDayOff: NSDate?
myDayOff <<< 1414172803 // You can also use unix timestamps.
You can deserialize instances and arrays of instances directly from a JSON string as well. Here is a quick example.
class Person: Deserializable {
var name = ""
required init(data: [String: AnyObject]) {
name <<< data["name"]
}
}
var jsonString = "[{\"name\": \"Rocket Raccoon\"}, {\"name\": \"Groot\"}]"
var people = [Person]()
people <<<<* jsonString
for person in people {
println("\(person.name)")
}