Skip to content

Instantly share code, notes, and snippets.

@bhargavg
Last active April 7, 2016 16:44
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/d1d16d04d342d5804d8b2ee7337b840e to your computer and use it in GitHub Desktop.
Save bhargavg/d1d16d04d342d5804d8b2ee7337b840e to your computer and use it in GitHub Desktop.
[
{
"name": {
"first_name": "Lex",
"last_name": "Luthor"
},
"age": 28,
"gender": "male",
"address": {
"city": "Edneyville",
"state": "Maine"
},
"skills": [
"laboris",
"id",
"consectetur",
"duis",
"incididunt",
"eiusmod"
]
},
{
"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": [
"Lorem",
"do",
"commodo",
"occaecat"
]
},
{
"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": "Oklahoma"
},
"skills": [
"sunt",
"et",
"et",
"ullamco",
"est",
"ipsum",
"laborum"
]
}
]
import Foundation
func get<T>(box:[String: AnyObject], key: String) -> T? {
return box[key] as? T
}
func get<T>(item: AnyObject) -> T? {
return item as? T
}
_ _
| |__ | |__ __ _ _ __ __ _ __ ___ ____ _
| '_ \| '_ \ / _` | '__/ _` |/ _` \ \ / / _` |
| |_) | | | | (_| | | | (_| | (_| |\ V / (_| |
|_.__/|_| |_|\__,_|_| \__, |\__,_| \_/ \__, |
|___/ |___/
Just a dummy text file to have a proper titles for gists 😒
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)
}
func parseGender(gender: String) -> Gender {
switch gender {
case "male":
return .Male
case "female":
return .Female
default:
return .Unknown
}
}
func parseName(data: [String: AnyObject]) -> String? {
return ["first_name", "last_name"].map{ data[$0] as? String }
.flatMap{ $0 }
.joinWithSeparator(", ")
}
func parseAddress(data: [String: AnyObject]) -> Address? {
let x = makeAddress <?> get(data, key: "street")
<*> get(data, key: "city")
<*> get(data, key: "state")
return x
}
func parseCustomer(data: [String: AnyObject]) -> Customer? {
return makeCustomer <*> get(data, key: "name") <~~ parseName
<*> get(data, key: "age")
<*> get(data, key: "gender") <~~ parseGender
<?> get(data, key: "address") <~~ parseAddress
<*> get(data, key: "skills")
}
let customers: [Customer]? = get(jsonData) <<~ parseCustomer
if let customers = customers {
// There are totally 5 customers in JSON,
// but 2nd customer doesn't have name property
// making it invalid
// So, this will only parse 4 customers successfully
print("Parsed: \(customers.count) customers")
print(customers)
} else {
print("Failed to parse")
}
// Models
struct Customer {
let name: String // first_name, last_name
let age: Int
let gender: Gender
let address: Address? //Optional
let skills: [String]
}
enum Gender {
case Unknown, Male, Female
}
struct Address {
let street: String?
let city: String
let state: String
}
// Curries
func makeAddress(street: String?) -> (city: String) -> (state: String) -> Address {
return { city in { state in
return Address(street: street, city: city, state: state)
}}
}
func makeCustomer(name: String) -> (age: Int) -> (gender: Gender) -> (address: Address?) -> (skills: [String]) -> Customer {
return { age in { gender in { address in { skills in
return Customer(name: name, age: age, gender: gender, address: address, skills: skills)
}}}}
}
infix operator <*> {
associativity left
precedence 100
}
infix operator <?> {
associativity left
precedence 100
}
infix operator <~~ {
associativity left
precedence 110
}
infix operator <<~ {
associativity left
precedence 110
}
func <*><A, B>(f: (A -> B)?, x: A?) -> B? {
guard let f = f, x = x else {
return nil
}
return f(x)
}
func <?><A, B>(f: (A? -> B)?, x: A?) -> B? {
guard let f = f else {
return nil
}
return f(x)
}
func <~~<A, B>(x: A?, f: (A -> B?)) -> B? {
guard let x = x else {
return nil
}
return f(x)
}
func <<~<A, B>(x: [A]?, f: (A -> B?)) -> [B]? {
guard let x = x else {
return nil
}
return x.map(f).flatMap{ $0 }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment