Skip to content

Instantly share code, notes, and snippets.

@bhargavg
Last active April 11, 2016 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bhargavg/9fc4189b696ead1c44c97854fe9ca02c to your computer and use it in GitHub Desktop.
Save bhargavg/9fc4189b696ead1c44c97854fe9ca02c to your computer and use it in GitHub Desktop.
{
"status": 200,
"response": {
"customers": [
{
"name": {
"first_name": "Lex",
"last_name": "Luthor"
},
"age": 28,
"gender": "male",
"address": {
"street": "244 Clifton Place",
"city": "Edneyville",
"state": null
},
"skills": null
},
{
"name": {
"first_name": "Ada",
"last_name": "Stuart"
},
"age": 29,
"gender": "female",
"address": {
"street": "754 Marconi Place",
"city": "Rosburg",
"state": "Louisiana"
},
"skills": [
"laborum",
"et",
"proident",
"dolor",
"exercitation",
"nisi"
]
},
{
"name": {
"first_name": "Judith",
"last_name": "Roach"
},
"age": 24,
"gender": "female",
"address": {
"street": "675 Reed Street",
"city": "Cochranville",
"state": "Pennsylvania"
},
"skills": null
},
{
"name": {
"first_name": "Jana",
"last_name": "Decker"
},
"age": 21,
"gender": "female",
"address": {
"street": "524 Bridge Street",
"city": "Gila",
"state": "New Hampshire"
},
"skills": [
"sit",
"irure",
"duis",
"sit"
]
},
{
"name": {
"first_name": "Lydia",
"last_name": "Maxwell"
},
"age": 31,
"gender": "female",
"address": {
"street": "596 Folsom Place",
"city": "Galesville",
"state": null
},
"skills": [
"sunt",
"et",
"et",
"ullamco",
"est",
"ipsum",
"laborum"
]
}
]
}
}
_ _
| |__ | |__ __ _ _ __ __ _ __ ___ ____ _
| '_ \| '_ \ / _` | '__/ _` |/ _` \ \ / / _` |
| |_) | | | | (_| | | | (_| | (_| |\ V / (_| |
|_.__/|_| |_|\__,_|_| \__, |\__,_| \_/ \__, |
|___/ |___/
Just a dummy text file to have a proper titles for gists 😒
import Foundation
func get<T>(box: [String: AnyObject], key: String) throws -> T {
typealias ParseErrorType = ParseError<String, T.Type>
guard let value = box[key] else {
throw ParseErrorType.NilValue(key)
}
guard let typedValue = value as? T else {
throw ParseErrorType.InvalidType(key, expected: T.self)
}
return typedValue
}
func get<T>(item: AnyObject) throws -> T {
guard let typedItem = item as? T else {
throw ParseError.InvalidType(item, expected: T.self)
}
return typedItem
}
func keyPath<T>(path: String) -> (box: [String: AnyObject]) throws -> T {
typealias ParseErrorType = ParseError<String, T.Type>
return { box in
guard let value = (box as NSDictionary).valueForKeyPath(path) else {
throw ParseErrorType.NilValue(path)
}
guard let typedValue = value as? T else {
throw ParseErrorType.InvalidType(path, expected: T.self)
}
return typedValue
}
}
import Foundation
guard let data = NSData(contentsOfFile: "customers.json"),
let jsonData = try? NSJSONSerialization.JSONObjectWithData(data, options: []) else {
print("Couldn't load JSON file")
exit(1)
}
do {
let customers: [Customer]? = try get(jsonData) <~~ keyPath("response.customers") <<~ Customer.init
print(customers)
} catch {
print(error)
}
import Foundation
struct Customer {
let name: String // first_name, last_name
let age: Int
let gender: Gender
let address: Address
let skills: [String]?
init(json: JSON) throws {
name = try get(json, key: "name") <~~ Customer.parseName
age = try get(json, key: "age")
gender = try get(json, key: "gender") <~~ Gender.parseGender
address = try get(json, key: "address") <~~ Address.init
skills = try? get(json, key: "skills")
}
static func parseName(data: [String: AnyObject]) -> String {
return ["first_name", "last_name"].map{ data[$0] as? String }
.flatMap{ $0 }
.joinWithSeparator(", ")
}
}
enum Gender {
case Unknown, Male, Female
static func parseGender(gender: String) -> Gender {
switch gender {
case "male":
return .Male
case "female":
return .Female
default:
return .Unknown
}
}
}
struct Address {
let street: String
let city: String
let state: String?
init(json: JSON) throws {
street = try get(json, key: "street")
city = try get(json, key: "city")
state = try? get(json, key: "state")
}
}
infix operator <~~ {
associativity left
precedence 110
}
infix operator <<~ {
associativity left
precedence 110
}
func <~~<A, B>(x: A, f: (A throws -> B)) throws -> B {
return try f(x)
}
func <<~<A, B>(x: [A], f: (A throws -> B)) throws -> [B] {
return try x.map(f)
}
typealias JSON = [String: AnyObject]
enum ParseError<T, U>: ErrorType {
case InvalidType(T, expected: U)
case NilValue(T)
}
extension ParseError: CustomStringConvertible {
var description: String {
switch self {
case .InvalidType(let aThing, let expectedType):
return "\(aThing) is not of type: \(expectedType)"
case .NilValue(let key):
return "\(key) is nil"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment