Arrow
๐น Parse JSON with style
[Reason](#reason) - [Example](#example) - [Installation](#installation) The project is written primarily in Swift, distributed under the MIT License license, first published in 2015. Key topics include: arrow, decoding, freshos, ios, json.

Arrow
Reason - Example - Installation
swiftidentifier <-- 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
Try it
Arrow is part of freshOS iOS toolset. Try it in an example App! <a class="github-button" href="https://github.com/freshOS/StarterProject/archive/master.zip" data-icon="octicon-cloud-download" data-style="mega" aria-label="Download freshOS/StarterProject on GitHub">Download Starter Project</a>
How
By using a simple arrow operator that takes care of the boilerplate code for us.
Json mapping code becomes concise and maintainable โค๏ธ
Why use Arrow
- Infers types
- Leaves your models clean
- Handles custom & nested models
- Dot and array syntax
- Pure Swift, Simple & Lightweight
Example
Swift Model
swiftstruct Profile { var identifier = 0 var name = "" var link:NSURL? var weekday:WeekDay = .Monday var stats = Stats() var phoneNumbers = [PhoneNumber]() }
JSON File
json{ "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" }] }
Before (Chaos)
swiftvar 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)) } }
After ๐๐๐
swiftextension 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"] } }
Usage
swiftlet profile = Profile() profile.deserialize(json)
Installation
The Swift Package Manager (SPM) is now the official way to install Arrow. The other package managers are now deprecated as of 5.1.2 and won't be supported in future versions.
Swift Package Manager
Xcode > File > Swift Packages > Add Package Dependency... > Paste https://github.com/freshOS/Arrow
Carthage - Deprecated
github "freshOS/Arrow"
CocoaPods - Deprecated
target 'MyApp'
pod 'Arrow'
use_frameworks!
How Does That Work
Notice earlier we typed :
swiftstats <-- json["stats"]
That's because we created and extension "Stats+Arrow.swift" enabling us to use the Arrow Operator
swift// Stats+Arrow.swift import Foundation extension Stats:ArrowParsable { mutating func deserialize(json: JSON) { numberOfFriends <-- json["numberOfFriends"] numberOfFans <-- json["numberOfFans"] } }
Flexible you said
- DO I have to use the <-- for my sub models
- Nope, you could write it like so if you wanted :
swiftstats.numberOfFriends <-- json["stats.numberOfFriends"] stats.numberOfFans <-- json["stats.numberOfFans"]
Date Parsing
Globally
swift// Configure Global Date Parsing with one of those Arrow.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ") Arrow.setUseTimeIntervalSinceReferenceDate(true) Arrow.setDateFormatter(aDateFormatter) // Then later dates can be parsed form custom date format or timestamps automatically ๐ let json:JSON = JSON(["date": "2013-06-07T16:38:40+02:00", "timestamp": 392308720]) date1 <-- json["date"] date2 <-- json["timestamp"]
On a per-key basis
swiftcreatedAt <-- json["created_at"]?.dateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ") createdAt <-- json["created_at"]?.dateFormatter(aCustomDateFormatter)
Just provide it on a case per case basis ! ๐
Accessing JSON values
Nested values
swiftvalue <-- json["nested.nested.nested.nestedValue"]
Object at index
swiftvalue <-- json[12]
Combine both
swiftvalue <-- json[1]?["someKey"]?[2]?["something.other"]
Looping on Array
swiftif let collection = json.collection { for jsonEntry in collection { //Do something } }
Swift Version
- Swift 2 -> version 2.0.3
- Swift 3 -> version 3.0.5
- Swift 4 -> version 4.0.0
- Swift 4.1 -> version 4.1.0
- Swift 4.2 -> version 4.2.0
- Swift 5.0 -> version 5.0.0
- Swift 5.1 -> version 5.1.0
- Swift 5.1.3 -> version 5.1.1
- Swift 5.3 -> version 6.0.0
Acknowledgements
This wouldn't exist without YannickDot, Damien-nd and maxkonovalov
Backers
Like the project? Offer coffee or support us with a monthly donation and help us continue our activities :)
<a href="https://opencollective.com/freshos/backer/0/website" target="_blank"><img src="https://opencollective.com/freshos/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/1/website" target="_blank"><img src="https://opencollective.com/freshos/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/2/website" target="_blank"><img src="https://opencollective.com/freshos/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/3/website" target="_blank"><img src="https://opencollective.com/freshos/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/4/website" target="_blank"><img src="https://opencollective.com/freshos/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/5/website" target="_blank"><img src="https://opencollective.com/freshos/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/6/website" target="_blank"><img src="https://opencollective.com/freshos/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/7/website" target="_blank"><img src="https://opencollective.com/freshos/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/8/website" target="_blank"><img src="https://opencollective.com/freshos/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/9/website" target="_blank"><img src="https://opencollective.com/freshos/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/10/website" target="_blank"><img src="https://opencollective.com/freshos/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/11/website" target="_blank"><img src="https://opencollective.com/freshos/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/12/website" target="_blank"><img src="https://opencollective.com/freshos/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/13/website" target="_blank"><img src="https://opencollective.com/freshos/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/14/website" target="_blank"><img src="https://opencollective.com/freshos/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/15/website" target="_blank"><img src="https://opencollective.com/freshos/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/16/website" target="_blank"><img src="https://opencollective.com/freshos/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/17/website" target="_blank"><img src="https://opencollective.com/freshos/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/18/website" target="_blank"><img src="https://opencollective.com/freshos/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/19/website" target="_blank"><img src="https://opencollective.com/freshos/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/20/website" target="_blank"><img src="https://opencollective.com/freshos/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/21/website" target="_blank"><img src="https://opencollective.com/freshos/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/22/website" target="_blank"><img src="https://opencollective.com/freshos/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/23/website" target="_blank"><img src="https://opencollective.com/freshos/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/24/website" target="_blank"><img src="https://opencollective.com/freshos/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/25/website" target="_blank"><img src="https://opencollective.com/freshos/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/26/website" target="_blank"><img src="https://opencollective.com/freshos/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/27/website" target="_blank"><img src="https://opencollective.com/freshos/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/28/website" target="_blank"><img src="https://opencollective.com/freshos/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/freshos/backer/29/website" target="_blank"><img src="https://opencollective.com/freshos/backer/29/avatar.svg"></a>
Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site :)
<a href="https://opencollective.com/freshos/sponsor/0/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/1/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/2/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/3/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/4/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/5/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/6/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/7/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/8/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/9/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/10/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/11/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/12/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/13/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/14/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/15/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/16/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/17/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/18/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/19/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/20/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/21/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/22/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/23/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/24/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/25/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/26/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/27/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/28/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/freshos/sponsor/29/website" target="_blank"><img src="https://opencollective.com/freshos/sponsor/29/avatar.svg"></a>
Contributors
Showing top 7 contributors by commit count.
