415 lines
9.9 KiB
Swift
415 lines
9.9 KiB
Swift
//: Playground - noun: a place where people can play
|
|
/*:
|
|
# SwiftyJSON
|
|
SwiftyJSON makes it easy to deal with JSON data in Swift.
|
|
|
|
You must have to build `SwiftyJSON iOS` package for import.
|
|
*/
|
|
/*:
|
|
### Basic setting for playground
|
|
*/
|
|
import SwiftyJSON
|
|
import Foundation
|
|
|
|
var jsonData: Data?
|
|
|
|
if let file = Bundle.main.path(forResource: "SwiftyJSONTests", ofType: "json") {
|
|
jsonData = try? Data(contentsOf: URL(fileURLWithPath: file))
|
|
} else {
|
|
print("Fail")
|
|
}
|
|
|
|
let jsonObject = try JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments)
|
|
|
|
let jsonString = String(data: jsonData!, encoding: .utf8)
|
|
|
|
/*:
|
|
## Usage
|
|
|
|
### Initialization
|
|
|
|
*/
|
|
|
|
let json1 = try? JSON(data: jsonData!)
|
|
/*:
|
|
or
|
|
*/
|
|
let json2 = JSON(jsonObject)
|
|
/*:
|
|
or
|
|
*/
|
|
let dataFromString = jsonString?.data(using: .utf8)
|
|
let json3 = try? JSON(data: dataFromString!)
|
|
|
|
/*:
|
|
### Subscript
|
|
*/
|
|
// Example json
|
|
let json: JSON = JSON([
|
|
"array": [12.34, 56.78],
|
|
"users": [
|
|
[
|
|
"id": 987654,
|
|
"info": [
|
|
"name": "jack",
|
|
"email": "jack@gmail.com"
|
|
],
|
|
"feeds": [98833, 23443, 213239, 23232]
|
|
],
|
|
[
|
|
"id": 654321,
|
|
"info": [
|
|
"name": "jeffgukang",
|
|
"email": "jeffgukang@gmail.com"
|
|
],
|
|
"feeds": [12345, 56789, 12423, 12412]
|
|
]
|
|
]
|
|
])
|
|
|
|
// Getting a double from a JSON Array
|
|
json["array"][0].double
|
|
|
|
// Getting an array of string from a JSON Array
|
|
let arrayOfString = json["users"].arrayValue.map({$0["info"]["name"]})
|
|
print(arrayOfString)
|
|
|
|
// Getting a string from a JSON Dictionary
|
|
json["users"][0]["info"]["name"].stringValue
|
|
|
|
// Getting a string using a path to the element
|
|
let path = ["users", 1, "info", "name"] as [JSONSubscriptType]
|
|
var name = json["users", 1, "info", "name"].string
|
|
|
|
// With a custom way
|
|
let keys: [JSONSubscriptType] = ["users", 1, "info", "name"]
|
|
name = json[keys].string
|
|
|
|
// Just the same
|
|
name = json["users"][1]["info"]["name"].string
|
|
|
|
// Alternatively
|
|
name = json["users", 1, "info", "name"].string
|
|
|
|
/*:
|
|
### Loop
|
|
*/
|
|
// If json is .Dictionary
|
|
for (key, subJson):(String, JSON) in json {
|
|
//Do something you want
|
|
print(key)
|
|
print(subJson)
|
|
}
|
|
|
|
/*The first element is always a String, even if the JSON is an Array*/
|
|
//If json is .Array
|
|
//The `index` is 0..<json.count's string value
|
|
for (index, subJson):(String, JSON) in json["array"] {
|
|
//Do something you want
|
|
print("\(index): \(subJson)")
|
|
}
|
|
|
|
/*:
|
|
### Error
|
|
|
|
SwiftyJSON 4.x
|
|
|
|
SwiftyJSON 4.x introduces an enum type called `SwiftyJSONError`, which includes `unsupportedType`, `indexOutOfBounds`, `elementTooDeep`, `wrongType`, `notExist` and `invalidJSON`, at the same time, `ErrorDomain` are being replaced by `SwiftyJSONError.errorDomain`. Note: Those old error types are deprecated in SwiftyJSON 4.x and will be removed in the future release.
|
|
|
|
Use a subscript to get/set a value in an Array or Dictionary
|
|
|
|
If the JSON is:
|
|
|
|
- an array, the app may crash with "index out-of-bounds."
|
|
- a dictionary, it will be assigned nil without a reason.
|
|
- not an array or a dictionary, the app may crash with an "unrecognised selector" exception.
|
|
|
|
This will never happen in SwiftyJSON.
|
|
*/
|
|
|
|
let errorJson = JSON(["name", "age"])
|
|
if let name = errorJson[999].string {
|
|
//Do something you want
|
|
print(name)
|
|
} else {
|
|
print(errorJson[999].error!) // "Array[999] is out of bounds"
|
|
}
|
|
|
|
let errorJson2 = JSON(["name": "Jack", "age": 25])
|
|
if let name = errorJson2["address"].string {
|
|
//Do something you want
|
|
print(name)
|
|
} else {
|
|
print(errorJson2["address"].error!) // "Dictionary["address"] does not exist"
|
|
}
|
|
|
|
let errorJson3 = JSON(12345)
|
|
if let age = errorJson3[0].string {
|
|
//Do something you want
|
|
print(age)
|
|
} else {
|
|
print(errorJson3[0]) // "Array[0] failure, It is not an array"
|
|
print(errorJson3[0].error!) // "Array[0] failure, It is not an array"
|
|
}
|
|
|
|
if let name = json["name"].string {
|
|
//Do something you want
|
|
print(name)
|
|
} else {
|
|
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
|
|
*/
|
|
|
|
// Example json
|
|
let jsonOG: JSON = JSON([
|
|
"id": 987654,
|
|
"user": [
|
|
"favourites_count": 8,
|
|
"name": "jack",
|
|
"email": "jack@gmail.com",
|
|
"is_translator": true
|
|
]
|
|
])
|
|
|
|
//NSNumber
|
|
if let id = jsonOG["user"]["favourites_count"].number {
|
|
//Do something you want
|
|
print(id)
|
|
} else {
|
|
//Print the error
|
|
print(jsonOG["user"]["favourites_count"].error!)
|
|
}
|
|
|
|
//String
|
|
if let id = jsonOG["user"]["name"].string {
|
|
//Do something you want
|
|
print(id)
|
|
} else {
|
|
//Print the error
|
|
print(jsonOG["user"]["name"].error!)
|
|
}
|
|
|
|
//Bool
|
|
if let id = jsonOG["user"]["is_translator"].bool {
|
|
//Do something you want
|
|
print(id)
|
|
} else {
|
|
//Print the error
|
|
print(jsonOG["user"]["is_translator"].error!)
|
|
}
|
|
|
|
/*:
|
|
### Non-optional getter
|
|
Non-optional getter is named xxxValue
|
|
*/
|
|
|
|
// Example json
|
|
let jsonNOG: JSON = JSON([
|
|
"id": 987654,
|
|
"name": "jack",
|
|
"list": [
|
|
["number": 1],
|
|
["number": 2],
|
|
["number": 3]
|
|
],
|
|
"user": [
|
|
"favourites_count": 8,
|
|
"email": "jack@gmail.com",
|
|
"is_translator": true
|
|
]
|
|
])
|
|
|
|
//If not a Number or nil, return 0
|
|
let idNOG: Int = jsonOG["id"].intValue
|
|
print(idNOG)
|
|
|
|
//If not a String or nil, return ""
|
|
let nameNOG: String = jsonNOG["name"].stringValue
|
|
print(nameNOG)
|
|
|
|
//If not an Array or nil, return []
|
|
let listNOG: Array = jsonNOG["list"].arrayValue
|
|
print(listNOG)
|
|
|
|
//If not a Dictionary or nil, return [:]
|
|
let userNOG: Dictionary = jsonNOG["user"].dictionaryValue
|
|
print(userNOG)
|
|
|
|
/*:
|
|
### Setter
|
|
*/
|
|
|
|
var jsonSetter: JSON = JSON([
|
|
"id": 987654,
|
|
"name": "jack",
|
|
"array": [0, 2, 4, 6, 8],
|
|
"double": 3513.352,
|
|
"dictionary": [
|
|
"name": "Jack",
|
|
"sex": "man"
|
|
],
|
|
"user": [
|
|
"favourites_count": 8,
|
|
"email": "jack@gmail.com",
|
|
"is_translator": true
|
|
]
|
|
])
|
|
|
|
jsonSetter["name"] = JSON("new-name")
|
|
jsonSetter["array"][0] = JSON(1)
|
|
|
|
jsonSetter["id"].int = 123456
|
|
jsonSetter["double"].double = 123456.789
|
|
jsonSetter["name"].string = "Jeff"
|
|
jsonSetter.arrayObject = [1, 2, 3, 4]
|
|
jsonSetter.dictionaryObject = ["name": "Jeff", "age": 20]
|
|
|
|
/*:
|
|
### Raw object
|
|
*/
|
|
|
|
let rawObject: Any = jsonSetter.object
|
|
|
|
let rawValue: Any = jsonSetter.rawValue
|
|
|
|
//convert the JSON to raw NSData
|
|
do {
|
|
let rawData = try jsonSetter.rawData()
|
|
print(rawData)
|
|
} catch {
|
|
print("Error \(error)")
|
|
}
|
|
|
|
//convert the JSON to a raw String
|
|
if let rawString = jsonSetter.rawString() {
|
|
print(rawString)
|
|
} else {
|
|
print("Nil")
|
|
}
|
|
|
|
/*:
|
|
### Existence
|
|
*/
|
|
|
|
// shows you whether value specified in JSON or not
|
|
if jsonSetter["name"].exists() {
|
|
print(jsonSetter["name"])
|
|
}
|
|
|
|
/*:
|
|
### Literal convertibles
|
|
For more info about literal convertibles: [Swift literal Convertibles](http://nshipster.com/swift-literal-convertible/)
|
|
*/
|
|
|
|
// StringLiteralConvertible
|
|
let jsonLiteralString: JSON = "I'm a json"
|
|
|
|
// IntegerLiteralConvertible
|
|
let jsonLiteralInt: JSON = 12345
|
|
|
|
// BooleanLiteralConvertible
|
|
let jsonLiteralBool: JSON = true
|
|
|
|
// FloatLiteralConvertible
|
|
let jsonLiteralFloat: JSON = 2.8765
|
|
|
|
// DictionaryLiteralConvertible
|
|
let jsonLiteralDictionary: JSON = ["I": "am", "a": "json"]
|
|
|
|
// ArrayLiteralConvertible
|
|
let jsonLiteralArray: JSON = ["I", "am", "a", "json"]
|
|
|
|
// With subscript in array
|
|
var jsonSubscriptArray: JSON = [1, 2, 3]
|
|
jsonSubscriptArray[0] = 100
|
|
jsonSubscriptArray[1] = 200
|
|
jsonSubscriptArray[2] = 300
|
|
jsonSubscriptArray[999] = 300 // Don't worry, nothing will happen
|
|
|
|
// With subscript in dictionary
|
|
var jsonSubscriptDictionary: JSON = ["name": "Jack", "age": 25]
|
|
jsonSubscriptDictionary["name"] = "Mike"
|
|
jsonSubscriptDictionary["age"] = "25" // It's OK to set String
|
|
jsonSubscriptDictionary["address"] = "L.A" // Add the "address": "L.A." in json
|
|
|
|
// Array & Dictionary
|
|
var jsonArrayDictionary: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
|
|
jsonArrayDictionary["list"][3]["what"] = "that"
|
|
jsonArrayDictionary["list", 3, "what"] = "that"
|
|
|
|
let arrayDictionarypath: [JSONSubscriptType] = ["list", 3, "what"]
|
|
jsonArrayDictionary[arrayDictionarypath] = "that"
|
|
|
|
// With other JSON objects
|
|
let user: JSON = ["username": "Steve", "password": "supersecurepassword"]
|
|
let auth: JSON = [
|
|
"user": user.object, //use user.object instead of just user
|
|
"apikey": "supersecretapitoken"
|
|
]
|
|
|
|
/*:
|
|
### Merging
|
|
|
|
It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the other JSON.
|
|
|
|
If both JSONs contain a value for the same key, mostly this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment:
|
|
|
|
- In case of both values being a JSON.Type.array the values form the array found in the other JSON getting appended to the original JSON's array value.
|
|
- In case of both values being a JSON.Type.dictionary both JSON-values are getting merged the same way the encapsulating JSON is merged.
|
|
|
|
In case, where two fields in a JSON have a different types, the value will get always overwritten.
|
|
|
|
There are two different fashions for merging: merge modifies the original JSON, whereas merged works non-destructively on a copy.
|
|
*/
|
|
var original: JSON = [
|
|
"first_name": "John",
|
|
"age": 20,
|
|
"skills": ["Coding", "Reading"],
|
|
"address": [
|
|
"street": "Front St",
|
|
"zip": "12345"
|
|
]
|
|
]
|
|
|
|
let update: JSON = [
|
|
"last_name": "Doe",
|
|
"age": 21,
|
|
"skills": ["Writing"],
|
|
"address": [
|
|
"zip": "12342",
|
|
"city": "New York City"
|
|
]
|
|
]
|
|
|
|
try original.merge(with: update)
|
|
print(original)
|
|
// [
|
|
// "first_name": "John",
|
|
// "last_name": "Doe",
|
|
// "age": 21,
|
|
// "skills": ["Coding", "Reading", "Writing"],
|
|
// "address": [
|
|
// "street": "Front St",
|
|
// "zip": "12342",
|
|
// "city": "New York City"
|
|
// ]
|
|
// ]
|
|
|
|
/*:
|
|
### String representation
|
|
There are two options available:
|
|
|
|
- use the default Swift one
|
|
- use a custom one that will handle optionals well and represent nil as "null":
|
|
*/
|
|
|
|
let stringRepresentationDict = ["1": 2, "2": "two", "3": nil] as [String: Any?]
|
|
let stringRepresentionJson: JSON = JSON(stringRepresentationDict)
|
|
let representation = stringRepresentionJson.rawString([.castNilToNSNull: true])
|
|
print(representation!)
|
|
// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null}
|