Latest 3.0.5
Homepage https://github.com/freshOS/Arrow
License MIT
Platforms ios 8.0, requires ARC

Arrow

Language: Swift 2 and 3
Platform: iOS 8+
Carthage compatible
Cocoapods compatible
Build Status
codebeat badge
License: MIT
[Release version]()

ReasonExampleInstallation

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

Try it

Arrow is part of freshOS iOS toolset. Try it in an example App ! Download Starter Project

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

  • [x] Infers types
  • [x] Leaves your models clean
  • [x] Handles custom & nested models
  • [x] Dot and array syntax
  • [x] Pure Swift, Simple & Lightweight

Example

Swift Model

struct Profile {
    var identifier = 0
    var name = ""
    var link:NSURL?
    var weekday:WeekDay = .Monday
    var stats = Stats()
    var phoneNumbers = [PhoneNumber]()
}

JSON File

{
    "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)

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))
    }
}

After 🎉🎉🎉

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"]
    }
}

Usage

let profile = Profile()
profile.deserialize(json)

Installation

Carthage

github "freshOS/Arrow"

CocoaPods

target 'MyApp'
pod 'Arrow'
use_frameworks!

Manually

Simply Copy and Paste .swift files in your Xcode Project :)

As A Framework

Grab this repository and build the Framework target on the example project. Then Link against this framework.

How Does That Work

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"]
    }
}

Flexible you said

  • 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"]

Date Parsing

Globally

// 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

createdAt <-- 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

value <-- json["nested.nested.nested.nestedValue"]

Object at index

value <-- json[12]

Combine both

value <-- json[1]?["someKey"]?[2]?["something.other"]

Looping on Array

if let collection = json.collection {
    for jsonEntry in collection {
        //Do something
    }
}

Swift Version

Swift 2 -> version 2.0.3
Swift 3 -> version 3.0.5

Acknoledgments

This wouldn’t exist without YannickDot, Damien-nd and maxkonovalov


Latest podspec

{
    "name": "Arrow",
    "version": "3.0.5",
    "summary": "Elegant JSON Parsing in Swift",
    "homepage": "https://github.com/freshOS/Arrow",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": "S4cha",
    "platforms": {
        "ios": "8.0"
    },
    "source": {
        "git": "https://github.com/freshOS/Arrow.git",
        "tag": "3.0.5"
    },
    "social_media_url": "https://twitter.com/sachadso",
    "source_files": "Source/*.swift",
    "requires_arc": true,
    "description": "Elegant Swift JSON Parsing - Stop writing boilerplate JSON parsing code and focus on your awesome App instead",
    "pushed_with_swift_version": "3.0"
}

Pin It on Pinterest

Share This