SwiftyJSON 使在 Swift 中处理 JSON 数据变得容易。
平台 | 构建状态 |
---|---|
*操作系统 | |
Linux |
Swift 在类型方面非常严格。虽然显式类型可以避免错误,但在处理 JSON 和其他本质上对类型隐式的领域时,它会变得很痛苦。
以 Twitter API 为例。假设我们想在 Swift 中检索某个推文的用户的“name”值(根据Twitter 的 API)。
代码如下所示
if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
let user = statusesArray[0]["user"] as? [String: Any],
let username = user["name"] as? String {
// Finally we got the username
}
这不好。
即使我们使用可选链,也会很混乱
if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String {
// There's our username
}
难以理解的混乱——对于一些本应很简单的事情!
使用 SwiftyJSON,您只需
let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
//Now you got your value
}
不用担心可选包装的问题。它会自动为您完成。
let json = JSON(data: dataFromNetworking)
let result = json[999999]["wrong_key"]["wrong_name"]
if let userName = result.string {
//Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety
} else {
//Print the error
print(result.error)
}
您可以使用 CocoaPods 通过将其添加到您的 Podfile
来安装 SwiftyJSON
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyJSON', '~> 4.0'
end
您可以使用 Carthage 通过将其添加到您的 Cartfile
来安装 SwiftyJSON
github "SwiftyJSON/SwiftyJSON" ~> 4.0
如果您使用 Carthage 构建您的依赖项,请确保您已将 SwiftyJSON.framework
添加到目标的“Linked Frameworks and Libraries”部分,并且已将其包含在您的 Carthage framework 复制构建阶段中。
您可以使用 Swift Package Manager 通过将正确的描述添加到您的 Package.swift
文件来安装 SwiftyJSON
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "YOUR_PROJECT_NAME",
dependencies: [
.package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
]
)
然后在您准备就绪时运行 swift build
。
要手动在您的项目中使用此库,您可以
import SwiftyJSON
let json = JSON(data: dataFromNetworking)
或
let json = JSON(jsonObject)
或
if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
}
// Getting a double from a JSON Array
let name = json[0].double
// Getting an array of string from a JSON Array
let arrayNames = json["users"].arrayValue.map {$0["name"].stringValue}
// Getting a string from a JSON Dictionary
let name = json["name"].stringValue
// Getting a string using a path to the element
let path: [JSONSubscriptType] = [1,"list",2,"name"]
let name = json[path].string
// Just the same
let name = json[1]["list"][2]["name"].string
// Alternatively
let name = json[1,"list",2,"name"].string
// With a hard way
let name = json[].string
// With a custom way
let keys:[JSONSubscriptType] = [1,"list",2,"name"]
let name = json[keys].string
// If json is .Dictionary
for (key,subJson):(String, JSON) in json {
// Do something you want
}
即使 JSON 是一个数组,第一个元素始终是一个字符串
// If json is .Array
// The `index` is 0..<json.count's string value
for (index,subJson):(String, JSON) in json {
// Do something you want
}
SwiftyJSON 4.x 引入了一个名为 SwiftyJSONError
的枚举类型,其中包括 unsupportedType
、indexOutOfBounds
、elementTooDeep
、wrongType
、notExist
和 invalidJSON
,同时,ErrorDomain
被 SwiftyJSONError.errorDomain
替换。注意:这些旧的错误类型在 SwiftyJSON 4.x 中已弃用,并在将来的版本中删除。
使用下标在数组或字典中获取/设置值
如果 JSON 是
nil
而没有理由。这在 SwiftyJSON 中永远不会发生。
let json = JSON(["name", "age"])
if let name = json[999].string {
// Do something you want
} else {
print(json[999].error!) // "Array[999] is out of bounds"
}
let json = JSON(["name":"Jack", "age": 25])
if let name = json["address"].string {
// Do something you want
} else {
print(json["address"].error!) // "Dictionary["address"] does not exist"
}
let json = JSON(12345)
if let age = json[0].string {
// Do something you want
} else {
print(json[0]) // "Array[0] failure, It is not an array"
print(json[0].error!) // "Array[0] failure, It is not an array"
}
if let name = json["name"].string {
// Do something you want
} else {
print(json["name"]) // "Dictionary[\"name"] failure, It is not an dictionary"
print(json["name"].error!) // "Dictionary[\"name"] failure, It is not an dictionary"
}
// NSNumber
if let id = json["user"]["favourites_count"].number {
// Do something you want
} else {
// Print the error
print(json["user"]["favourites_count"].error!)
}
// String
if let id = json["user"]["name"].string {
// Do something you want
} else {
// Print the error
print(json["user"]["name"].error!)
}
// Bool
if let id = json["user"]["is_translator"].bool {
// Do something you want
} else {
// Print the error
print(json["user"]["is_translator"].error!)
}
// Int
if let id = json["user"]["id"].int {
// Do something you want
} else {
// Print the error
print(json["user"]["id"].error!)
}
...
非可选 getter 被命名为 xxxValue
// If not a Number or nil, return 0
let id: Int = json["id"].intValue
// If not a String or nil, return ""
let name: String = json["name"].stringValue
// If not an Array or nil, return []
let list: Array<JSON> = json["list"].arrayValue
// If not a Dictionary or nil, return [:]
let user: Dictionary<String, JSON> = json["user"].dictionaryValue
json["name"] = JSON("new-name")
json[0] = JSON(1)
json["id"].int = 1234567890
json["coordinate"].double = 8766.766
json["name"].string = "Jack"
json.arrayObject = [1,2,3,4]
json.dictionaryObject = ["name":"Jack", "age":25]
let rawObject: Any = json.object
let rawValue: Any = json.rawValue
//convert the JSON to raw NSData
do {
let rawData = try json.rawData()
//Do something you want
} catch {
print("Error \(error)")
}
//convert the JSON to a raw String
if let rawString = json.rawString() {
//Do something you want
} else {
print("json.rawString is nil")
}
// shows you whether value specified in JSON or not
if json["name"].exists()
有关字面量转换的更多信息:Swift 字面量转换
// StringLiteralConvertible
let json: JSON = "I'm a json"
/ /IntegerLiteralConvertible
let json: JSON = 12345
// BooleanLiteralConvertible
let json: JSON = true
// FloatLiteralConvertible
let json: JSON = 2.8765
// DictionaryLiteralConvertible
let json: JSON = ["I":"am", "a":"json"]
// ArrayLiteralConvertible
let json: JSON = ["I", "am", "a", "json"]
// With subscript in array
var json: JSON = [1,2,3]
json[0] = 100
json[1] = 200
json[2] = 300
json[999] = 300 // Don't worry, nothing will happen
// With subscript in dictionary
var json: JSON = ["name": "Jack", "age": 25]
json["name"] = "Mike"
json["age"] = "25" // It's OK to set String
json["address"] = "L.A." // Add the "address": "L.A." in json
// Array & Dictionary
var json: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]]
json["list"][3]["what"] = "that"
json["list",3,"what"] = "that"
let path: [JSONSubscriptType] = ["list",3,"what"]
json[path] = "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"
]
可以将一个 JSON 合并到另一个 JSON 中。将一个 JSON 合并到另一个 JSON 会将所有仅存在于 other
JSON 中的非现有值添加到原始 JSON 中。
如果两个 JSON 都包含相同键的值,通常此值会在原始 JSON 中被覆盖,但在两种情况下会提供一些特殊处理
JSON.Type.array
,则 other
JSON 中的值将被附加到原始 JSON 的数组值。JSON.Type.dictionary
,则两个 JSON 值将以封装 JSON 合并的相同方式进行合并。如果 JSON 中两个字段具有不同的类型,则该值将始终被覆盖。
有两种不同的合并方式:merge
修改原始 JSON,而 merged
对副本进行非破坏性操作。
let 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"
]
]
let updated = original.merge(with: update)
// [
// "first_name": "John",
// "last_name": "Doe",
// "age": 21,
// "skills": ["Coding", "Reading", "Writing"],
// "address": [
// "street": "Front St",
// "zip": "12342",
// "city": "New York City"
// ]
// ]
有两个选项可用
nil
表示为 "null"
的自定义选项let dict = ["1":2, "2":"two", "3": nil] as [String: Any?]
let json = JSON(dict)
let representation = json.rawString(options: [.castNilToNSNull: true])
// representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null}
SwiftyJSON 很好地包装了 Alamofire JSON 响应处理程序的结果
Alamofire.request(url, method: .get).validate().responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
print("JSON: \(json)")
case .failure(let error):
print(error)
}
}
我们还提供了 Alamofire 的扩展,用于将 NSData 序列化为 SwiftyJSON 的 JSON。
SwiftyJSON 将数据解析为 JSON
let provider = MoyaProvider<Backend>()
provider.request(.showProducts) { result in
switch result {
case let .success(moyaResponse):
let data = moyaResponse.data
let json = JSON(data: data) // convert network data to json
print(json)
case let .failure(error):
print("error: \(error)")
}
}
生成 SwiftyJSON 模型的工具