Last active
January 6, 2017 07:05
-
-
Save jarsen/b27de2ed9e84b84086ae to your computer and use it in GitHub Desktop.
This file contains hidden or 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) 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") | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
}