Created
June 15, 2015 21:28
-
-
Save jarsen/10150c39301834da398f 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 | |
struct Address { | |
var street: String | |
} | |
struct Person { | |
var name: String | |
var age: Int | |
var dutch: Bool | |
var address: Address? | |
} | |
extension MirrorType { | |
var children: [(String, MirrorType)] { | |
var result: [(String, MirrorType)] = [] | |
for i in 0..<self.count { | |
result.append(self[i]) | |
} | |
return result | |
} | |
} | |
typealias JSONObject = [String:AnyObject] | |
protocol JSONCodable { | |
func toJSON() throws -> AnyObject? | |
static func fromJSON(value: AnyObject) throws -> Self | |
static func fromJSON(object: JSONObject, key: String) throws -> Self | |
} | |
enum JSONError : ErrorType { | |
case NotSerializable(source: Any, type: MirrorType) | |
case NoValueForKey(String) | |
case TypeMismatch(expected: MirrorType, got: MirrorType) | |
} | |
extension JSONCodable { | |
func toJSON() throws -> AnyObject? { | |
let mirror = reflect(self) | |
if mirror.count > 0 { | |
var result: [String:AnyObject] = [:] | |
for (key, child) in mirror.children { | |
if let value = child.value as? JSONCodable { | |
result[key] = try value.toJSON() | |
} else { | |
throw JSONError.NotSerializable(source: self, type: child) | |
} | |
} | |
return result | |
} | |
return self as? AnyObject | |
} | |
static func fromJSON(object: JSONObject, key: String) throws -> Self { | |
if let value = object[key] { | |
return try self.fromJSON(value) | |
} | |
throw JSONError.NoValueForKey(key) | |
} | |
} | |
extension Int: JSONCodable { | |
static func fromJSON(value: AnyObject) throws -> Int { | |
if let x = value as? Int { | |
return x | |
} | |
throw JSONError.TypeMismatch(expected: reflect(Int), got: reflect(value)) | |
} | |
} | |
extension String: JSONCodable { | |
static func fromJSON(value: AnyObject) throws -> String { | |
if let x = value as? String { | |
return x | |
} | |
throw JSONError.TypeMismatch(expected: reflect(String), got: reflect(value)) | |
} | |
} | |
extension Bool: JSONCodable { | |
static func fromJSON(value: AnyObject) throws -> Bool { | |
if let x = value as? Bool { | |
return x | |
} | |
throw JSONError.TypeMismatch(expected: reflect(Bool), got: reflect(value)) | |
} | |
} | |
extension Address: JSONCodable { | |
static func fromJSON(value: AnyObject) throws -> Address { | |
if let object = value as? JSONObject { | |
let street = try String.fromJSON(object, key: "street") | |
return Address(street: street) | |
} | |
throw JSONError.TypeMismatch(expected: reflect(Bool), got: reflect(value)) | |
} | |
} | |
extension Person: JSONCodable { | |
static func fromJSON(value: AnyObject) throws -> Person { | |
if let object = value as? JSONObject { | |
let name = try String.fromJSON(object, key: "name") | |
let age = try Int.fromJSON(object, key: "age") | |
let dutch = try Bool.fromJSON(object, key: "dutch") | |
let address = try Address?.fromJSON(object, key: "address") | |
return Person(name: name, age: age, dutch: dutch, address: address) | |
} | |
throw JSONError.TypeMismatch(expected: reflect(Person), got: reflect(value)) | |
} | |
} | |
extension Optional: JSONCodable { | |
func toJSON() throws -> AnyObject? { | |
if let x = self { | |
if let value = x as? JSONCodable { | |
return try value.toJSON() | |
} | |
throw JSONError.NotSerializable(source: x, type: reflect(x)) | |
} | |
return nil | |
} | |
static func fromJSON(value: AnyObject) throws -> T? { | |
return .Some(try (T.self as! JSONCodable).dynamicType.fromJSON(value) as! T) | |
if T.self is JSONCodable { | |
return .Some(try (T.self as! JSONCodable).dynamicType.fromJSON(value) as! T) | |
} | |
throw JSONError.NotSerializable(source: value, type: reflect(value)) | |
} | |
static func fromJSON(object: JSONObject, key: String) throws -> T? { | |
if let value = object[key] { | |
value | |
print(value) | |
return try self.fromJSON(value)! | |
} | |
return .None | |
} | |
} | |
do { | |
// let person = try Person.fromJSON(["name": "Jason", "age": 27, "dutch": false]) | |
let person = try Person.fromJSON(["name": "Jason", "age": 27, "address": ["street" : "A Street"], "dutch": false]) | |
let object2 = try person.toJSON() | |
} | |
catch let JSONError.NoValueForKey(key) { | |
print(key) | |
} | |
catch let JSONError.TypeMismatch(expected: a, got: b) { | |
print(a) | |
print(b) | |
} | |
catch { | |
print(error) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment