Skip to content

Instantly share code, notes, and snippets.

@jarsen
Last active August 29, 2015 14:23
Show Gist options
  • Save jarsen/2b0913111c0427642c41 to your computer and use it in GitHub Desktop.
Save jarsen/2b0913111c0427642c41 to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
import UIKit
enum JSONError : ErrorType {
case NoValueForKey(String)
case TypeMismatch
}
public class JSONObject {
private let dictionary: [String:AnyObject]
public init(dictionary: [String:AnyObject]) {
self.dictionary = dictionary
}
func valueForKey<A>(key: String, type: A.Type) throws -> A {
let pathComponents = key.componentsSeparatedByString(".")
var accumulator: Any = dictionary
for component in pathComponents {
if let dict = accumulator as? [String:AnyObject] {
if let value = dict[component] {
accumulator = value
continue
}
}
throw JSONError.NoValueForKey(key)
}
if let value = accumulator as? A {
return value
}
else {
throw JSONError.TypeMismatch
}
}
func stringForKey(key: String) throws -> String {
return try valueForKey(key, type: String.self)
}
func intForKey(key: String) throws -> Int {
return try valueForKey(key, type: Int.self)
}
func doubleForKey(key: String) throws -> Double {
return try valueForKey(key, type: Double.self)
}
func arrayForKey<A>(key: String, type: A.Type) throws -> [A] {
return try valueForKey(key, type: [A].self)
}
func objectForKey(key: String) throws -> JSONObject {
let dict = try valueForKey(key, type: [String:AnyObject].self)
return JSONObject(dictionary: dict)
}
func optionalForKey<A>(key: String, type: A.Type) throws -> A? {
do {
let value = try valueForKey(key, type: type)
return value
}
catch JSONError.NoValueForKey {
return nil
}
catch {
throw JSONError.TypeMismatch
}
}
func stringOptionalForKey(key: String) throws -> String? {
return try optionalForKey(key, type: String.self)
}
func intOptionalForKey(key: String) throws -> Int? {
return try optionalForKey(key, type: Int.self)
}
func doubleOptionalForKey(key: String) throws -> Double? {
return try optionalForKey(key, type: Double.self)
}
func arrayOptionalForKey<A>(key: String, type: A.Type) throws -> [A]? {
return try optionalForKey(key, type: [A].self)
}
func objectOptionalForKey(key: String) throws -> JSONObject? {
let dict = try optionalForKey(key, type: [String:AnyObject].self)
return dict.map(JSONObject.init)
}
}
struct Person {
var name: String
var age: Int
var height: Double
var street: String?
static func fromJSON(json: JSONObject) throws -> Person {
let name = try json.stringForKey("name")
let age = try json.intForKey("age")
let height = try json.doubleForKey("height")
let street = try json.stringForKey("address.street")
let _ = try json.stringOptionalForKey("address.street2") // nil
return Person(name: name, age: age, height: height, street: street)
}
}
do {
let json = JSONObject(dictionary: ["name": "Bob", "age": 26.5, "height": 5.75, "address": ["street": "A Street"]])
let foo = try json.intForKey("age")
let person = try Person.fromJSON(json)
}
catch let JSONError.NoValueForKey(key) {
print("Didn't find value for key: \(key)")
}
catch {
print("Wrong type")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment