JSON Parsing
by JaSON Larsen
@jarsen
JSON Parsing
by JaSON Larsen
@jarsen
JSONValue Extraction
by JaSON Larsen
@jarsen
The History
Inthe beginning...
if let id = json["id"] as? Int {
if let name = json["name"] as? String {
if let email = json["email"] as? String {
// create user
}
}
}
Swift 1.2
if let id = json["id"] as? Int,
name = json["name"] as? String,
email = json["email"] as? String {
// create user
}
else {
// return some error, ex: `Result<T>`
}
Swift 2
guard let id = json["id"] as? Int,
name = json["name"] as? String,
email = json["email"] as? String {
// throw some error
}
// create user
Argo
extension User: Decodable {
static func decode(j: JSON) -> Decoded<User> {
return curry(User.init) // used to have to make a separate `make` function
<^> j <| "id"
<*> j <| "name"
<*> j <|? "email" // Use ? for parsing optional values
<*> j <| "role" // Custom types that also conform to Decodable just work
<*> j <| ["company", "name"] // Parse nested objects
<*> j <|| "friends" // parse arrays of objects
}
}
(https://github.com/thoughtbot/Argo)
WhatYouThink
WhatYourTeam
Thinks
JSONArrays...
var pets = [Pet]()
if let petsObjects = json["pets"] as? [JSONObject] {
for petObject in petsObjects {
guard let id = petObject["id"] as? Int,
name = petObject["name"] as? String else {
continue // or throw error if less tolerant
}
let pet = Pet(id: id, name: name)
pets.append(pet)
}
}
Whyso muchwork?
Wouldn'titbe greatif...
struct User : JSONObjectConvertible {
let id: Int
let name: String
let email: String?
let pets: [Pet]
init(json: JSONObject) throws {
id = try json.valueForKey("id")
name = try json.valueForKey("name")
email = try json.valueForKey("email")
pets = try json.valueForKey("pets")
}
}
The Implementation
Playground Gist
https://gist.github.com/jarsen/672aa5969689c5864cac
Caveat: Core DataModels
For NSManagedObject subclasses JSONObjectConvertible
won't really work because init is not so simple...
public protocol JSONDecoding {
func update(json: JSONObject) throws
}
Caveat: Core DataModels
class User: NSManagedObject, JSONDecoding {
@NSManaged var name: String
@NSManaged var email: String
func update(json: JSONObject) throws {
try name = json.valueForKey("name")
try email = json.valueForKey("email")
}
}
MatthewCheok'sJSONCodable
extension User: JSONEncodable {
func toJSON() throws -> AnyObject {
return try JSONEncoder.create({ (encoder) -> Void in
try encoder.encode(id, key: "id")
try encoder.encode(name, key: "full_name")
try encoder.encode(email, key: "email")
try encoder.encode(company, key: "company")
try encoder.encode(friends, key: "friends")
})
}
}
(https://github.com/matthewcheok/JSONCodable)
SpecialThanks
» Bart Whiteley
» Brian Mullen
» BJ Homer
» Derrick Hathaway
» Dave DeLong
» Mark Schultz
» Tim Shadel
Resources
» My blog jasonlarsen.me (look for No-Magic JSON
series)
» JaSON https://github.com/jarsen/JaSON
» JaSON (extension on Dictionary) https://
github.com/bwhiteley/JaSON

Protocol Oriented JSON Parsing in Swift

  • 1.
    JSON Parsing by JaSONLarsen @jarsen
  • 2.
    JSON Parsing by JaSONLarsen @jarsen
  • 3.
  • 4.
  • 5.
    Inthe beginning... if letid = json["id"] as? Int { if let name = json["name"] as? String { if let email = json["email"] as? String { // create user } } }
  • 6.
    Swift 1.2 if letid = json["id"] as? Int, name = json["name"] as? String, email = json["email"] as? String { // create user } else { // return some error, ex: `Result<T>` }
  • 7.
    Swift 2 guard letid = json["id"] as? Int, name = json["name"] as? String, email = json["email"] as? String { // throw some error } // create user
  • 8.
    Argo extension User: Decodable{ static func decode(j: JSON) -> Decoded<User> { return curry(User.init) // used to have to make a separate `make` function <^> j <| "id" <*> j <| "name" <*> j <|? "email" // Use ? for parsing optional values <*> j <| "role" // Custom types that also conform to Decodable just work <*> j <| ["company", "name"] // Parse nested objects <*> j <|| "friends" // parse arrays of objects } } (https://github.com/thoughtbot/Argo)
  • 10.
  • 12.
  • 13.
    JSONArrays... var pets =[Pet]() if let petsObjects = json["pets"] as? [JSONObject] { for petObject in petsObjects { guard let id = petObject["id"] as? Int, name = petObject["name"] as? String else { continue // or throw error if less tolerant } let pet = Pet(id: id, name: name) pets.append(pet) } }
  • 14.
  • 15.
    Wouldn'titbe greatif... struct User: JSONObjectConvertible { let id: Int let name: String let email: String? let pets: [Pet] init(json: JSONObject) throws { id = try json.valueForKey("id") name = try json.valueForKey("name") email = try json.valueForKey("email") pets = try json.valueForKey("pets") } }
  • 16.
  • 17.
  • 18.
    Caveat: Core DataModels ForNSManagedObject subclasses JSONObjectConvertible won't really work because init is not so simple... public protocol JSONDecoding { func update(json: JSONObject) throws }
  • 19.
    Caveat: Core DataModels classUser: NSManagedObject, JSONDecoding { @NSManaged var name: String @NSManaged var email: String func update(json: JSONObject) throws { try name = json.valueForKey("name") try email = json.valueForKey("email") } }
  • 20.
    MatthewCheok'sJSONCodable extension User: JSONEncodable{ func toJSON() throws -> AnyObject { return try JSONEncoder.create({ (encoder) -> Void in try encoder.encode(id, key: "id") try encoder.encode(name, key: "full_name") try encoder.encode(email, key: "email") try encoder.encode(company, key: "company") try encoder.encode(friends, key: "friends") }) } } (https://github.com/matthewcheok/JSONCodable)
  • 21.
    SpecialThanks » Bart Whiteley »Brian Mullen » BJ Homer » Derrick Hathaway » Dave DeLong » Mark Schultz » Tim Shadel
  • 22.
    Resources » My blogjasonlarsen.me (look for No-Magic JSON series) » JaSON https://github.com/jarsen/JaSON » JaSON (extension on Dictionary) https:// github.com/bwhiteley/JaSON