buzzfeed/SwiftyJSON

Name: SwiftyJSON

Owner: BuzzFeed

Description: The better way to deal with JSON data in Swift

Created: 2016-08-23 21:53:19.0

Updated: 2016-08-23 21:53:20.0

Pushed: 2016-08-24 15:21:42.0

Homepage:

Size: 561

Language: Swift

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

SwiftyJSON

Travis CI

SwiftyJSON makes it easy to deal with JSON data in Swift.

  1. Why is the typical JSON handling in Swift NOT good
  2. Requirements
  3. Integration
  4. Usage
  5. Work with Alamofire

For Swift3 support, take a look at the swift3 beta branch

????

Why is the typical JSON handling in Swift NOT good?

Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types.

Take the Twitter API for example. Say we want to retrieve a user's “name” value of some tweet in Swift (according to Twitter's API https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline).

The code would look like this:

et statusesArray = try? NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]],
let user = statusesArray[0]["user"] as? [String: AnyObject],
let username = user["name"] as? String {
// Finally we got the username

It's not good.

Even if we use optional chaining, it would be messy:

et JSONObject = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]],
let username = (JSONObject[0]["user"] as? [String: AnyObject])?["name"] as? String {
    // There's our username

An unreadable mess–for something that should really be simple!

With SwiftyJSON all you have to do is:

json = JSON(data: dataFromNetworking)
et userName = json[0]["user"]["name"].string {
Now you got your value

And don't worry about the Optional Wrapping thing. It's done for you automatically.

json = JSON(data: dataFromNetworking)
et userName = json[999999]["wrong_key"]["wrong_name"].string {
//Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
se {
//Print the error
print(json[999999]["wrong_key"]["wrong_name"])

Requirements
Integration
CocoaPods (iOS 8+, OS X 10.9+)

You can use Cocoapods to install SwiftyJSONby adding it to your Podfile:

form :ios, '8.0'
frameworks!

et 'MyApp' do
pod 'SwiftyJSON'

Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 8.0:

Carthage (iOS 8+, OS X 10.9+)

You can use Carthage to install SwiftyJSON by adding it to your Cartfile:

ub "SwiftyJSON/SwiftyJSON"
Swift Package Manager

You can use The Swift Package Manager to install SwiftyJSON by adding the proper description to your Package.swift file:

rt PackageDescription

package = Package(
name: "YOUR_PROJECT_NAME",
targets: [],
dependencies: [
    .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: "2.3.3" ..< Version.max)
]

Note that the Swift Package Manager is still in early design and development, for more infomation checkout its GitHub Page

Manually (iOS 7+, OS X 10.9+)

To use this library in your project manually you may:

  1. for Projects, just drag SwiftyJSON.swift to the project tree
  2. for Workspaces, include the whole SwiftyJSON.xcodeproj
Usage
Initialization
rt SwiftyJSON
json = JSON(data: dataFromNetworking)
json = JSON(jsonObject)
et dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)

Subscript
tting a double from a JSON Array
name = json[0].double
tting a string from a JSON Dictionary
name = json["name"].stringValue
tting a string using a path to the element
path = [1,"list",2,"name"]
name = json[path].string
st the same
name = json[1]["list"][2]["name"].string
ternatively
name = json[1,"list",2,"name"].string
th a hard way
name = json[].string
th a custom way
keys:[SubscriptType] = [1,"list",2,"name"]
name = json[keys].string
Loop
 json is .Dictionary
(key,subJson):(String, JSON) in json {
/Do something you want

The first element is always a String, even if the JSON is an Array

 json is .Array
e `index` is 0..<json.count's string value
(index,subJson):(String, JSON) in json {
//Do something you want

Error

Use a subscript to get/set a value in an Array or Dictionary

If the JSON is:

This will never happen in SwiftyJSON.

json = JSON(["name", "age"])
et name = json[999].string {
//Do something you want
se {
print(json[999].error) // "Array[999] is out of bounds"

json = JSON(["name":"Jack", "age": 25])
et name = json["address"].string {
//Do something you want
se {
print(json["address"].error) // "Dictionary["address"] does not exist"

json = JSON(12345)
et age = json[0].string {
//Do something you want
se {
print(json[0])       // "Array[0] failure, It is not an array"
print(json[0].error) // "Array[0] failure, It is not an array"


et name = json["name"].string {
//Do something you want
se {
print(json["name"])       // "Dictionary[\"name"] failure, It is not an dictionary"
print(json["name"].error) // "Dictionary[\"name"] failure, It is not an dictionary"

Optional getter
Number
et id = json["user"]["favourites_count"].number {
/Do something you want
se {
/Print the error
rint(json["user"]["favourites_count"].error)

ring
et id = json["user"]["name"].string {
/Do something you want
se {
/Print the error
rint(json["user"]["name"])

ol
et id = json["user"]["is_translator"].bool {
/Do something you want
se {
/Print the error
rint(json["user"]["is_translator"])

t
et id = json["user"]["id"].int {
/Do something you want
se {
/Print the error
rint(json["user"]["id"])


Non-optional getter

Non-optional getter is named xxxValue

 not a Number or nil, return 0
id: Int = json["id"].intValue
 not a String or nil, return ""
name: String = json["name"].stringValue
 not a Array or nil, return []
list: Array<JSON> = json["list"].arrayValue
 not a Dictionary or nil, return [:]
user: Dictionary<String, JSON> = json["user"].dictionaryValue
Setter
["name"] = JSON("new-name")
[0] = JSON(1)
["id"].int =  1234567890
["coordinate"].double =  8766.766
["name"].string =  "Jack"
.arrayObject = [1,2,3,4]
.dictionary = ["name":"Jack", "age":25]
Raw object
jsonObject: AnyObject = json.object
et jsonObject: AnyObject = json.rawValue
nvert the JSON to raw NSData
et data = json.rawData() {
//Do something you want

nvert the JSON to a raw String
et string = json.rawString() {
//Do something you want

Existance
ows you whether value specified in JSON or not
son["name"].isExists()
Literal convertibles

For more info about literal convertibles: Swift Literal Convertibles

ringLiteralConvertible
json: JSON = "I'm a json"
tegerLiteralConvertible
json: JSON =  12345
oleanLiteralConvertible
json: JSON =  true
oatLiteralConvertible
json: JSON =  2.8765
ctionaryLiteralConvertible
json: JSON =  ["I":"am", "a":"json"]
rayLiteralConvertible
json: JSON =  ["I", "am", "a", "json"]
lLiteralConvertible
json: JSON =  nil
th subscript in array
json: JSON =  [1,2,3]
[0] = 100
[1] = 200
[2] = 300
[999] = 300 //Don't worry, nothing will happen
th subscript in dictionary
json: JSON =  ["name": "Jack", "age": 25]
["name"] = "Mike"
["age"] = "25" //It's OK to set String
["address"] = "L.A." // Add the "address": "L.A." in json
ray & Dictionary
json: JSON =  ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
["list"][3]["what"] = "that"
["list",3,"what"] = "that"
path = ["list",3,"what"]
[path] = "that"
Work with Alamofire

SwiftyJSON nicely wraps the result of the Alamofire JSON response handler:

ofire.request(.GET, url).validate().responseJSON { response in
switch response.result {
case .Success:
    if let value = response.result.value {
      let json = JSON(value)
      print("JSON: \(json)")
    }
case .Failure(let error):
    print(error)
}


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.