Related blog post: http://bhargavg.com/swift/2016/04/05/parsing-arrays-in-json.html
[ | |
{ | |
"name": { | |
"first_name": "Lex", | |
"last_name": "Luthor" | |
}, | |
"age": 28, | |
"gender": "male", | |
"address": { | |
"street": "244 Clifton Place", | |
"city": "Edneyville", | |
"state": "Maine" | |
}, | |
"skills": [ | |
"laboris", | |
"id", | |
"consectetur", | |
"duis", | |
"incididunt", | |
"eiusmod" | |
] | |
}, | |
{ | |
"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": [ | |
"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" | |
] | |
} | |
] |
struct Customer { | |
let name: String // first_name, last_name | |
let age: Int | |
let gender: Gender | |
let address: Address | |
let skills: [String] | |
} | |
enum Gender { | |
case Unknown, Male, Female | |
} | |
struct Address { | |
let street: String | |
let city: String | |
let state: String | |
} | |
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) | |
}}}} | |
} |
func get<T>(box:[String: AnyObject], key: String) -> T? { | |
return box[key] as? T | |
} | |
func get<T>(item: AnyObject) -> T? { | |
return item as? T | |
} |
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? { | |
return makeAddress <*> get(data, key: "street") | |
<*> get(data, key: "city") | |
<*> get(data, key: "state") | |
} | |
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 = get(jsonData) <<~ parseCustomer | |
guard let customers = customers else { | |
print("Couldn't parse customers") | |
exit(1) | |
} | |
print(customers) |
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>(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