GitHub 中文社区iosiOS Developer

【译】SwiftyJSON 中文文档翻译

2017-02-13  本文已影响229人  HideOnBush

前言

最近正在编写 iOS APP 的后台接口,调试的时候要解析JSON数据,所以就来学习使用 SwiftyJSON 这个第三方库,但网上搜的资料感觉写的都不怎么样,最后就只能硬着头皮看官方的文档了,尝试着翻译,借此机会学习并且提高一下自己的 English 水平吧。Let's GO. (PS: 虽然官网也有中文翻译,但是好像不是很全。。。。。😆).如果有翻译错误❎,请见谅也请指出,谢谢!

SwiftyJSON 使得在 Swift 下处理 JSON 数据变得非常容易。

  1. [为什么在 Swift 下处理 JSON 数据的方式不是很好](#为什么在 Swift 下处理 JSON 数据的方式不是很好)
  2. 需求
  3. 整合
  4. 用法
  5. [和 Alamofire 一起使用](#和 Alamofire 一起使用)

为什么在 Swift 下处理 JSON 数据的方式不是很好

Swift 是一种严格的类型安全的语言。尽管明确的类型有利于我们减少错误,但是当我们在处理 JSON 和 其他隐式数据类型的时候就变得很痛苦。

拿 Twitter API 举个栗子。我将在 Swift 的下取回一个用户的 “名字”(根据 Twitter 的 API https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline)。

代码是这样子的:

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)
if let userName = json[999999]["wrong_key"]["wrong_name"].string {
  //calm down, take it easy. the ".string" property still produces the current Optional String type with safety
} else {
  //print the error
  print(json[999999]["wrong_ket"]["wrong_name"])
}

需求

整合

CocoaPods(iOS 8+, OS X 10.9+)

你可以使用 CocoaPods 来 安装 SwiftyJSON ,只要把一下的添加到 Podfile :

platform :iOS, '8.0'
use_frameworks!

target 'YourAPPName' do
pod 'SwiftyJSON'
end

注意这需要 CocoaPods 版本 36,并且你的 iOS 开发版本至少是 8.0:

Carthage(iOS 8+,OS X 10.9+)

你可以通过使用 Cathage 来安装 SwiftyJSON ,只需把一下的添加到 Cartfile:

github "SwiftyJOSN/SwiftyJSON"
Swift Package Manager

你可以使用 The Swift Package Manager 来安装 SwiftyJSON ,只需添加合适的描述到你的 Package.swift 文件:

import PackageDescription

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

注意, Swift Package Manager 任然处于早期设计和开发阶段,更多信息请查看 GitHub Page

手动添加(iOS7+,OS X 10.9+)

为了在你的项目中使用这个库你通常需要:

  1. 对于单个项目,只需将 SwiftyJSON.swift 拖进你的项目
  2. 对于工作组,包含整个 SwiftyJSON.xcodeproj

用法

初始化
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)
}
下标
//从 JSON数组 中获取一个 double
let name = json[0].double
//从一个 JSON数组 里获取一个 字符串数组
let arrayNames = json["users"].arrayValue.map({$0["name"].stringValue})
//从一个 JSON字典 中获取一个 string
let name = json["name"].stringValue
//通过元素的路径来获取 string
let path: [JSONSubscriptType] = [1, "list", 2, "name"]
let name = json[path].string
//同样的
let name = json[1]["list"][2]["name"].string
//或者
let name = json[1, "list", 2, "name"].string
//条件苛刻的情况
let name = json[].string
//普通的方法
let keys: [SubscriptType] = [1, "list", 2, "name"]
let name = json[keys].string
循环
//如果 JSON 是字典
for (key, subJson):(String, JSON) in json {
  //做你想做的事情
}

即使 JSON 是数组,第一个元素也总是字符串。

//如果 JSON是数组
//index 是0到JSON数量的一个字符串值
for (index, subJson):(String, JSON) in json {
  //做你想做的事情
}
错误

使用下标来获取或设置字典或数组里的一个值

如果 JSON 是:

这些在 SwiftyJSON 中都不会发生。

let json = JSON(["name", "age"])
if let name = json[999].string {
  //做你想做的事情
} else {
  print(json[999].error)//"Array[999] 已经越界了"
}
let json = JSON(["name":"Jack", "age": 25])
if let name = json["address"].string {
  //做你想做的事情
} else {
  print(json["address"].error)//"Dictionary["address"]并不存在"
}
let json = JSON(12345)
if let age = json[0].string {
  //做你想做的事情
} else {
  print(json[0]) // "Array[0] 失败,这不是一个数组"
  print(json[0].error) // "Array[0] 失败, 这不是一个数组"
}

if let name = json["name"].string {
  //做你想做的事情
} else {
  print(json["name"]) //"Dictionary[\"name"] 失败, 这不是一个字典"
  print(json["name"].error) //"Dictionary[\"name"] 失败,这不是一个字典"
}
Optional getter
//数字
if let id = json["user"]["favourites_count"].number {
  //做你想做的事情
} else {
  //打印错误
  print(json["user"]["favourites_count"].error)
}
//字符串
if let id = json["user"]["name"].string {
  //做你想做的事情
} else {
  //打印错误
  print(json["user"]["name"])
}
//bool
if let id = json["user"]["is_translator"].bool {
  //做你想做的事情
} else {
  //打印错误
  print(json["user"]["is_translator"])
}
//整型
if let id = json["user"]["id"].int {
  //做你想做的事情
} else {
  //打印错误
  print(json["user"]["id"])
}
...
Non-optional getter

非可选 getter 名为 xxxValue

//如果不是数字或者空,返回 0
let id : Int = json["id"].intValue
//如果不是字符串或者空,返回 ""
let name: String = json["name"].stringValue
//如果不是数组或者空,返回 []
let list: Array<JSON> = json["list"].arrayValue
 //如果不是字典或者空,返回 [:]
 let user: Dictionary<String, JSON> = json["user"].dictionaryValue
setter
json["name"] = JSON("new-name")
json[0] = JSON(1)
json["id"].int = 1234567890
json["coordinate"].double = 9766.766
json["name"].string = "jack"
json.arrayObject = [1, 2, 3, 4]
json.dictionaryObject = ["name" : "Jack", "age" : 25]
元对象
let jsonObject: Any = json.object
if let jsonObject: Any = json.rawValue
//把 JSON 转化为字符串元
if let data = json.rawData() {
  //做你想做的事情
}
//把 字符串元转化为 JSON
if let string = json.rawString() {
  //做你想做的事情
}
存在性
//用来显示 JSON 中是否有指定的值
if json["name"].exist()
文字转换

更多关于文字转换的信息:Swift Literal Convertibles

//字符串转换
let json: JSON = "I'm a json"
//整型转换
let json: JSON = 1234
//Bool型转换
let json: JSON = true
//单精度浮点数转换
let json: JSON = 2.8756
//字典转换
let json: JSON = ["I" : "am", "a" : "json"]
//数组转换
let json: JSON = ["I", "am", "a", "json"]
//空转换
let json: JSON = nil
//带有下标的数组
var json: JSON = [1, 2, 3]
json[0] = 100
json[1] = 200
json[3] = 300
json[999] = 300 //别担心, 什么都不会发生
//带有下标的字典
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"]
jaon[path] = "that"
//带有其他的 JSON 对象
let user: JSON = ["username" : "Strve", "password" : "supersecurepassword"]
let auth: JSON = [
  "user": user.object //使用 user.object 替代 user
  "apikey": "supersecuretapitoken"
]
合并

把一个 JSON 与另外一个 JSON 合并是可能的。合并两个 JSON 会把原始 JSON 中不存在的只出现在另外一个 JSON 中的数据添加进来。

如果两个 JSON 包含了的值有相同的键,通常情况下会重写原JSON的值,但是有两种情况下会有特别的处理:

在JSON中的两个字段具有不同类型的情况下,值将始终被覆盖。

有两种不同的方式合并: merge 修改原始的 JSON ,而合并在副本上以非破坏性方式工作。

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

文字表示

有两种可选可以用:

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}

和 Alamofire 一起使用

SWiftyJSON 很好地包装了 Alamofire JSON 相应的结果:

Alamofire.request(url, mothod: .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)
  }
}
上一篇下一篇

猜你喜欢

热点阅读