Last active
August 29, 2015 14:23
-
-
Save jarsen/2b0913111c0427642c41 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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