Reason - Example - Installation
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 (~200lines)
- Pure Swift
- Leaves your models clean
- Implicitly casts JSON values to the right types in your model
- Automatic NSDate, NSURL, Enum, Custom model Parsing
- Converts string values to numeric types in your model
- Does not crash if JSON key is not there, nor returns nil, it simply doesn't do anything
- No overly complex obscure functional chaining operator overloading voodoo magic ?==:>>><> π
struct Profile {
var identifier = 0
var name = ""
var link:NSURL?
var weekday:WeekDay = .Monday
var stats = Stats()
var phoneNumbers = [PhoneNumber]()
}
{
"id": 15678,
"name": "John Doe",
"link": "https://apple.com/steve",
"weekdayInt" : 3,
"stats": {
"numberOfFriends": 163,
"numberOfFans": 10987
},
"phoneNumbers": [{
"label": "house",
"number": "9809876545"
}, {
"label": "cell",
"number": "0908070656"
}, {
"label": "work",
"number": "0916570656"
}]
}
var profile = Profile()
// Int
if let id = json["id"] as? Int {
profile.identifier = id
}
// String
if let name = json["name"] as? String {
profile.name = name
}
// NSURL
if let link = json["link"] as? String, url = NSURL(string:link) {
profile.link = link
}
// Enum
if let weekdayInt = json["weekdayInt"] as? Int, weekday = WeekDay(rawValue:weekdayInt) {
profile.weekday = weekday
}
// Custom nested object
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
}
}
// Array of custom nested object
if let pns = json["phoneNumbers"] as? [AnyObject] {
for pn in pns {
phoneNumbers.append(PhoneNumber(json: pn))
}
}
extension Profile:ArrowParsable {
mutating func deserialize(json: JSON) {
identifier <-- json["id"]
link <-- json["link"]
name <-- json["name"]
weekday <-- json["weekdayInt"]
stats <- json["stats"]
phoneNumbers <-- json["phoneNumbers"]
}
}
let profile = Profile()
profile.deserialize(json)
github "s4cha/Arrow"
pod 'Arrow'
use_frameworks!
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.
Notice earlier we typed :
stats <-- json["stats"]
That's because we created and extension "Stats+Arrow.swift" enabling us to use the Arrow Operator
// Stats+Arrow.swift
import Foundation
extension Stats:ArrowParsable {
mutating func deserialize(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["stats.numberOfFriends"]
stats.numberOfFans <-- json["stats.numberOfFans"]
- Hey I don't want to parse NSDates in every files, do you have something for me?
Sure, just set your date format once and you're done.
// Configure NSDate Parsing
Arrow.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ")
Arrow.setUseTimeIntervalSinceReferenceDate(true)
// Dates can be parsed form custom date format or timestamp
let json:JSON = JSON(["date": "2013-06-07T16:38:40+02:00", "timestamp": 392308720])
date1 <-- json["date"]
date2 <-- json["timestamp"]
What if I want a Custom NSDate format for a specific key ?
createdAt <-- json["created_at"]?.dateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ")
Just provide it on a case per case basis ! π
value <-- json["nested.nested.nested.nestedValue"]
value <-- json[12]
value <-- json[1]?["someKey"]?[2]?["something.other"]
if let collection = json.collection {
for jsonEntry in collection {
//Do something
}
}
This wouldn't exist without YannickDot, Damien-nd and maxkonovalov
Arrow is part of a series of lightweight libraries aiming to make developing iOS Apps a breeze :