Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
//: 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) 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 objectForKey(key: String) throws -> JSONObject {
let dict: [String:AnyObject] = try valueForKey(key)
return JSONObject(dictionary: dict)
}
func optionalForKey<A>(key: String) throws -> A? {
do {
return try valueForKey(key)
}
catch JSONError.NoValueForKey {
return nil
}
catch {
throw JSONError.TypeMismatch
}
}
func objectOptionalForKey(key: String) throws -> JSONObject? {
let dict: [String:AnyObject]? = try optionalForKey(key)
return dict.map(JSONObject.init)
}
}
struct Person {
var name: String
var age: Int
var height: Double
var street: String?
init(json: JSONObject) throws {
try name = json.valueForKey("name")
try age = json.valueForKey("age")
try height = json.valueForKey("height")
try street = json.optionalForKey("address.street")
}
}
do {
let json = JSONObject(dictionary: ["name": "Bob", "age": 26.5, "height": 5.75, "address": ["street": "A Street"]])
let foo: Int = try json.valueForKey("age")
let person = try Person(json: json)
}
catch let JSONError.NoValueForKey(key) {
print("Didn't find value for key: \(key)")
}
catch {
print("Wrong type")
}

optionalForKey() doesn't work. A small adjustment is needed:
func optionalForKey(key: String) throws -> A? {
do {
return try valueForKey(key) as A // <-- "as A" otherwise the return value of valueForKey is optional and always produces a TypeMismatch error.
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment