Elegant JSON Parsing in Swift
identifier <-- json["id"]
name <-- json["name"]
stats <== json["stats"]
if let id = json["id"] as? Int {
identifier = id
}
if let n = json["name"] as? String {
name = n
}
if let s = Stats(json:json) {
stats = s
}
identifier <-- json["id"]
name <-- json["name"]
stats <== json["stats"]
Because parsing JSON in Swift is full of unecessary if lets, obvious casts and nil-checks
There must be a better way
By using a simple arrow operator that takes care of the boilerplate code for us.
Json mapping code becomes concise and maintainable β€οΈ
- Simple & Lightweight (~50lines)
- Pure Swift
- Leaves your models clean
- Implicitly casts JSON values to the right types in your model
- Does not crash if JSON key is not there, nor returns nil, it simply doesn't do anything
- NSDate Parsing
- No overly complex obscure functional chaining operator overloading voodoo magic ?==:>>><> π
github "s4cha/Arrow"
Simply Copy and Paste Arrow.swift in your Xcode Project :) https://github.com/s4cha/Arrow/blob/master/Arrow.swift
Grab this repository and build the Framework target on the example project. Then Link against this framework.
struct Profile {
var identifier = 0
var name = ""
var stats = Stats()
}
{
"id": 15678,
"name": "John Doe",
"stats": {
"numberOfFriends": 163,
"numberOfFans": 10987
}
}
var profile = Profile()
if let id = json["id"] as? Int {
profile.identifier = id
}
if let name = json["name"] as? String {
profile.name = name
}
if let statsJson = json["stats"] as? AnyObject {
if let numberOfFans = statsJson["numberOfFans"] as? Int {
profile.stats.numberOfFans = numberOfFans
}
if let numberOfFriends = statsJson["numberOfFriends"] as? Int {
profile.stats.numberOfFriends = numberOfFriends
}
}
extension Profile:ArrowParsable {
init(json: JSON) {
identifier <-- json["id"]
name <-- json["name"]
stats <== json["stats"]
}
}
- Step 1 - Copy paste Arrow.swift in your Xcode Project
- Step 2 - Create you model parsing extension like so : "Profile+Arrow.swift"
// Profile+Arrow.swift
extension Profile:ArrowParsable {
init(json: JSON) {
identifier <-- json["id"]
name <-- json["name"]
stats <== json["stats"]
}
}
- Step 3 - Use it:
let profile = Profile(json: json)
- Step 4 - Ther is no step 4
- <-- Arrow Operator is for all Swift Types : Int.. Double .. String .. NSDate etc
- <== Thick Arrow Operator is for your own custom models
Notice earlier we typed :
stats <== json["stats"]
That's because we created and extension "Stats+Arrow.swift" enabling us to use the thick Arrow Operator
// Stats+Arrow.swift
import Foundation
extension Stats:ArrowParsable {
init(json: JSON) {
numberOfFriends <-- json["numberOfFriends"]
numberOfFans <-- json["numberOfFans"]
}
}
- DO I have to use the <== for my sub models
- Nope, you could write it like so if you wanted :
stats.numberOfFriends <-- json.valueForKeyPath("stats.numberOfFriends")
stats.numberOfFans <-- json.valueForKeyPath("stats.numberOfFans")
- Hey I don't want to parse NSDates in evry files, do you have something for me?
Sure, just set your date format once and you're done.
// Configure NSDate Parsing
Arrow.dateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ")
This wouldn't exist without YannickDot (https://github.com/YannickDot) and Damien-nd (https://github.com/damien-nd) <3
Arrow is part of a series of lightweight libraries aiming to make developing iOS Apps a breeze :