SwiftyJson 实现Json转模型
JSON是移動端開發(fā)常用的應用層數(shù)據(jù)交換協(xié)議。最常見的場景便是,客戶端向服務端發(fā)起網(wǎng)絡請求,服務端返回JSON文本,然后客戶端解析這個JSON文本,再把對應數(shù)據(jù)展現(xiàn)到頁面上。
但在編程的時候,處理JSON是一件麻煩事。在不引入任何輪子的情況下,我們通常需要先把JSON轉為Dictionary,然后還要記住每個數(shù)據(jù)對應的Key,用這個Key在Dictionary中取出對應的Value來使用。這個過程我們會犯各種錯誤:
* Key拼寫錯了
* 路徑寫錯了
* 類型搞錯了
* 沒拿到值懵逼了
* 某一天和服務端約定的某個字段變更了,沒能更新所有用到它的地方
* ...
為了解決這些問題,很多處理JSON的開源庫應運而生。在Swift中,這些開源庫主要朝著兩個方向努力:
1. 保持JSON語義,直接解析JSON,但通過封裝使調用方式更優(yōu)雅、更安全
2. 預定義Model類,將JSON反序列化為類實例,再使用這些實例
對于1,使用最廣、評價最好的庫非 SwiftyJSON 莫屬,它很能代表這個方向的核心。它本質上仍然是根據(jù)JSON結構去取值,使用起來順手、清晰。但也正因如此,這種做法沒能妥善解決上述的幾個問題,因為Key、路徑、類型仍然需要開發(fā)者去指定;
對于2,我個人覺得這是更合理的方式。由于Model類的存在,JSON的解析和使用都受到了定義的約束,只要客戶端和服務端約定好了這個Model類,客戶端定義后,在業(yè)務中使用數(shù)據(jù)時就可以享受到語法檢查、屬性預覽、屬性補全等好處,而且一旦數(shù)據(jù)定義變更,編譯器會強制所有用到的地方都改過來才能編譯通過,非常安全。這個方向上,開源庫們做的工作,主要就是把JSON文本反序列化到Model類上了。這一類JSON庫有 ObjectMapper、JSONNeverDie、HandyJSON 等。
今天我們先來看看SwiftyJSON的用法。
通常我們拿到數(shù)據(jù)會進行非常麻煩的optinonal(可選類型)進行拆包(Wrapping )操作,
SwiftyJson內部會自動對optional進行拆包,大大簡化了代碼,解析非常方便,拿到的json數(shù)據(jù)data直接扔進去
//轉成JSON對象
let jsonData = JSON.init(data)
不管需要什么數(shù)據(jù)只要通過對jsonData進行路徑讀取
例如:
值得一提的是,不需要考慮服務器給我們返回的是什么類型,比如去請求一個房屋的棟數(shù)"build_num": 588我們想要獲得Int類型或者String類型都可以
let room_num1 = jsonData[0]["build_num"].stringValue
let room_num2 = jsonData[0]["build_num"].intValue
// room_num1 = 588 String類型
// room_num2 = 588 Int類型
這樣通過.stringValue.intValue就可以獲得不可選值類型,如果沒有獲取到數(shù)據(jù)的話就會返回一個默認值即.stringValue獲得空字符串"",.intValue得到0,.arrayValue獲得空數(shù)組[],我們就不用判斷拆包了。
當然某些場景可能需要你得到可選值類型并自己判斷是否存在,那么我們可以通過.string .int .bool .float .array .dictionary等等方法獲取,例如:
//String
if let build_name = jsonData[0]["build_name"].string {
print(build_name)
} else {
//打印錯誤信息
print(jsonData[0]["build_name"])
}
解析數(shù)據(jù)是真的非常簡單。詳細使用可以看看SwiftyJSON的使用詳解(附樣例)
或者移步GitHub-SwiftyJson
但是對于項目而言我們需要對數(shù)據(jù)進行轉換為模型,僅僅是對data進行JSON讀取是遠遠不夠的,想想,如果遇到許多地方都用到了build_name值,但是當服務器給我們返回的字段名字改了,我們改項目時就會顯得麻煩,甚至造成改不完全,所以我們隊數(shù)據(jù)封裝一下轉為模型,這樣修改時只用改一個地方就是model的賦值就好了。
那我的方法是:
//這是模擬數(shù)據(jù)
let baseInfo: [String : Any] = ["build_name":"置信·原墅",
"build_address":"學院中路與金橋路交匯處東北側",
"build_num": 12,
"room_num": 588,
"area_address":"浙江省溫州市鹿城區(qū)五馬街道"]
創(chuàng)建struct模型,當然Class也可以,但是如果不需要繼承也不復雜推薦struct(-。-不多解釋了)
并寫好創(chuàng)建方法
import SwiftyJSON
struct BuildBaseInfoModel {
var build_name: String?
var build_address: String?
var build_num: String?
var room_num: String?
var area_address: String?
init(jsonData: JSON) {
build_name = jsonData["build_name"].stringValue
build_address = jsonData["build_address"].stringValue
area_address = jsonData["area_address"].stringValue
room_num = jsonData["room_num"].stringValue
build_num = jsonData["build_num"].stringValue
}
}
調用:
let jsonData = JSON(baseInfo)
let model = BuildBaseInfoModel.init(jsonData: jsonData)
// 會得到創(chuàng)建好的 BuildBaseInfoModel類型的 對象model
// 也可以這樣寫
let model = BuildBaseInfoModel(jsonData: jsonData)
當然這只是普通的模型,經(jīng)常會遇到復雜模型,例如:
// 面積中89是Int, 109和129是String
let baseInfo: [String : Any] = ["build_name":"置信·原墅",
"build_address":"學院中路與金橋路交匯處東北側",
"area_address":"浙江省溫州市鹿城區(qū)五馬街道",
"area":[89,"109","129"],
"detail_address":["province":"浙江省",
"city":"溫州市",
"district":"鹿城區(qū)",
"street":"五馬街道"],
"build_num": 12,
"room_num": 588]
這時候模型就應該有兩個
struct BuildBaseInfoModel {
var build_name: String?
var build_address: String?
var build_num: String?
var room_num: String?
var area_address: String?
var detail_address: DetailAddressModel
var area:[Any]?
// 這里面積area中就不能再用arrayValue獲取了,因為arrayValue獲取的為JSON類型,我們需要轉為我們需要的對象
init(jsonData: JSON) {
build_name = jsonData["build_name"].stringValue
build_address = jsonData["build_address"].stringValue
area_address = jsonData["area_address"].stringValue
room_num = jsonData["room_num"].stringValue
build_num = jsonData["build_num"].stringValue
area = jsonData["area"].arrayObject
detail_address = DetailAddressModel(jsonData: jsonData["detail_address"])
}
}
struct DetailAddressModel {
var province: String?
var city: String?
var district: String?
var street: String?
init(jsonData: JSON) {
province = jsonData["province"].stringValue
city = jsonData["city"].stringValue
district = jsonData["district"].stringValue
street = jsonData["street"].stringValue
}
}
let model = BuildBaseInfoModel(jsonData: jsonData)
DPrint(message: model.detail_address.city)
DPrint(message: model.area?.first)
DPrint(message: model.area?[1])
// xxxxxxxxx.swift[21], updateRoomsData(index:): Optional("溫州市")
// xxxxxxxxx.swift[22], updateRoomsData(index:): Optional(89)
// xxxxxxxxx.swift[22], updateRoomsData(index:): Optional("109")
總結
以上是生活随笔為你收集整理的SwiftyJson 实现Json转模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java导出导入Excel方法
- 下一篇: 对单片机毕业设计的理解