一 簡(jiǎn)介
二 特性
三 安裝使用以及封裝
四 使用示例
一 簡(jiǎn)介
HandyJSON
是一個(gè)用于Swift
語言中的JSON
序列化/反序列化庫制肮。
與其他流行的Swift JSON
庫相比,HandyJSON
的特點(diǎn)是,它支持純swift
類,使用也簡(jiǎn)單惰赋。它反序列化時(shí)(把JSON轉(zhuǎn)換為Model)不要求Model
從NSObject
繼承(因?yàn)樗皇腔?code>KVC機(jī)制)宠哄,也不要求你為Model
定義一個(gè)Mapping
函數(shù)。只要你定義好Model
類府蛇,聲明它服從HandyJSON
協(xié)議,HandyJSON
就能自行以各個(gè)屬性的屬性名為Key
,從JSON
串中解析值敲才。
HandyJSON
目前依賴于從Swift Runtime
源碼中推斷的內(nèi)存規(guī)則,任何變動(dòng)我們將隨時(shí)跟進(jìn)校坑。
二 特性
- 序列化
Model
到JSON穷遂、從JSON反序列化
到Model
- 自然地以
Model
的屬性名稱作為解析JSON
的Key
函匕,不需要額外指定- 支持
Swift
中大部分類型- 支持
class
、struct
定義的Model
- 支持自定義解析規(guī)則
- 類型自適應(yīng)蚪黑,如
JSON
中是一個(gè)Int
盅惜,但對(duì)應(yīng)Model
是String
字段,會(huì)自動(dòng)完成轉(zhuǎn)化
三 安裝使用以及封裝
3.1 安裝
我使用的是cocopod
進(jìn)行包引入管理忌穿,修改Prodfie
文件抒寂,添加如下代碼:
pod 'HandyJSON'
3.2 封裝
為了方便我們項(xiàng)目中的使用,我們一般都會(huì)在做一層封裝
掠剑,方便庫的以后升級(jí)替換
屈芜,以及方便日常業(yè)務(wù)邏輯的處理
JsonUtil.swift
import UIKit
import HandyJSON
class JsonUtil: NSObject {
/**
* Json轉(zhuǎn)對(duì)象
*/
static func jsonToModel(_ jsonStr:String,_ modelType:HandyJSON.Type) ->BaseModel {
if jsonStr == "" || jsonStr.count == 0 {
#if DEBUG
print("jsonoModel:字符串為空")
#endif
return BaseModel()
}
return modelType.deserialize(from: jsonStr) as! BaseModel
}
/**
* Json轉(zhuǎn)數(shù)組對(duì)象
*/
static func jsonArrayToModel(_ jsonArrayStr:String, _ modelType:HandyJSON.Type) ->[BaseModel] {
if jsonArrayStr == "" || jsonArrayStr.count == 0 {
#if DEBUG
print("jsonToModelArray:字符串為空")
#endif
return []
}
var modelArray:[BaseModel] = []
let data = jsonArrayStr.data(using: String.Encoding.utf8)
let peoplesArray = try! JSONSerialization.jsonObject(with:data!, options: JSONSerialization.ReadingOptions()) as? [AnyObject]
for people in peoplesArray! {
modelArray.append(dictionaryToModel(people as! [String : Any], modelType))
}
return modelArray
}
/**
* 字典轉(zhuǎn)對(duì)象
*/
static func dictionaryToModel(_ dictionStr:[String:Any],_ modelType:HandyJSON.Type) -> BaseModel {
if dictionStr.count == 0 {
#if DEBUG
print("dictionaryToModel:字符串為空")
#endif
return BaseModel()
}
return modelType.deserialize(from: dictionStr) as! BaseModel
}
/**
* 對(duì)象轉(zhuǎn)JSON
*/
static func modelToJson(_ model:BaseModel?) -> String {
if model == nil {
#if DEBUG
print("modelToJson:model為空")
#endif
return ""
}
return (model?.toJSONString())!
}
/**
* 對(duì)象轉(zhuǎn)字典
*/
static func modelToDictionary(_ model:BaseModel?) -> [String:Any] {
if model == nil {
#if DEBUG
print("modelToJson:model為空")
#endif
return [:]
}
return (model?.toJSON())!
}
}
說明:這里我封裝了5個(gè)方法,Json
轉(zhuǎn)對(duì)象朴译,Json
轉(zhuǎn)數(shù)組對(duì)象
井佑,字典
轉(zhuǎn)對(duì)象
,對(duì)象
轉(zhuǎn)JSON
动分,對(duì)象
轉(zhuǎn)字典
,基本覆蓋了我們?nèi)粘i_發(fā)的常用操作毅糟,與這個(gè)工具類相對(duì)應(yīng)的,還有一個(gè)公共的基礎(chǔ)module
類
BaseModel.swift
import UIKit
import HandyJSON
class BaseModel: HandyJSON {
// var date: Date?
// var decimal: NSDecimalNumber?
// var url: URL?
// var data: Data?
// var color: UIColor?
required init() {}
func mapping(mapper: HelpingMapper) { //自定義解析規(guī)則澜公,日期數(shù)字顏色姆另,如果要指定解析格式,子類實(shí)現(xiàn)重寫此方法即可
// mapper <<<
// date <-- CustomDateFormatTransform(formatString: "yyyy-MM-dd")
//
// mapper <<<
// decimal <-- NSDecimalNumberTransform()
//
// mapper <<<
// url <-- URLTransform(shouldEncodeURLString: false)
//
// mapper <<<
// data <-- DataTransform()
//
// mapper <<<
// color <-- HexColorTransform()
}
}
說明:封裝的基礎(chǔ)model
類坟乾。開發(fā)中迹辐,我們自定義的model
繼承此model
即可省去了每次都要引入 “import HandyJSON”
,以及每次都要實(shí)現(xiàn)“required init() {}”
方法甚侣,子類如果要自定義解析規(guī)則明吩,重寫mapping
方法即可
四 使用示例
基于以上封裝的類我們實(shí)現(xiàn)幾個(gè)示例做具體說明,主要有以下幾個(gè)示例:
- Json轉(zhuǎn)模型 (常用)
- Json數(shù)組轉(zhuǎn)模型 (常用)
- 字典轉(zhuǎn)模型
- 模型轉(zhuǎn)Json
- 模型轉(zhuǎn)字典
- json與嵌套的模型相互轉(zhuǎn)換特殊類型字段轉(zhuǎn)換殷费,日期類型印荔,數(shù)字類型,顏色
1. Json轉(zhuǎn)模型 (常用)
JsonToModel.swift
import UIKit
class JsonToModel: BaseModel {
var id :Int?
var color:String?
var name:String?
}
fileprivate func jsonTomodel(){
let jsonString = "{\"id\":12345,\"color\":\"black\",\"name\":\"cat\"}"
let model:JsonToModel = JsonUtil.jsonToModel(jsonString,JsonToModel.self) as! JsonToModel
print(model.name as Any)
print(model.color as Any)
print(model.id as Any)
}
說明:調(diào)用jsonToModel(_ jsonStr:String,_ modelType:HandyJSON.Type)
,傳入兩個(gè)參數(shù)详羡,第一個(gè)參數(shù)是要轉(zhuǎn)換的Json
字符串仍律,第二個(gè)參數(shù)是要轉(zhuǎn)換的model
類的class
,因?yàn)楣差愔薪y(tǒng)一返回的都是BaseModel
類型实柠,所以這里要調(diào)用 as!
轉(zhuǎn)換成具體的子類類型水泉。
2. Json數(shù)組轉(zhuǎn)模型 (常用)
JsonArrayToModel.swift
import UIKit
class JsonArrayToModel: BaseModel {
var name:String?
var id :String?
}
//json數(shù)組轉(zhuǎn)模型
fileprivate func jsonArrayTomodel() {
let jsonArrayString: String = "[{\"name\":\"Bob\",\"id\":\"1\"}, {\"name\":\"Lily\",\"id\":\"2\"}, {\"name\":\"Lucy\",\"id\":\"3\"}]"
let cats = JsonUtil.jsonArrayToModel(jsonArrayString, JsonArrayToModel.self) as! [JsonArrayToModel]
for model:JsonArrayToModel in cats {
print(model.name as Any)
}
}
說明:調(diào)用jsonArrayToModel(_ jsonArrayStr:String, _ modelType:HandyJSON.Type)
傳入兩個(gè)參數(shù),第一個(gè)參數(shù)是要轉(zhuǎn)換的數(shù)組型Json
字符串,第二個(gè)參數(shù)是要轉(zhuǎn)換的model
類的class
草则,返回值是一個(gè)數(shù)組钢拧,因?yàn)楣差愔薪y(tǒng)一返回的都是BaseModel
類型,所以這里要調(diào)用as!
轉(zhuǎn)換成具體的子類類型數(shù)組炕横。
3 字典轉(zhuǎn)模型
import UIKit
class JsonToModel: BaseModel {
var id :Int!
var color:String?
var name:String?
}
//字典轉(zhuǎn)模型
fileprivate func dicToModel() {
var dict = [String: Any]()
dict["id"] = 1.1
dict["color"] = "hello"
dict["name"] = "李四"
let model:JsonToModel = JsonUtil.dictionaryToModel(dict,JsonToModel.self) as! JsonToModel
print(model.name as Any)
print(model.color as Any)
print(model.id as Any)
}
說明:調(diào)用dictionaryToModel(_ dictionStr:[String:Any],_ modelType:HandyJSON.Type)
源内,傳入兩個(gè)參數(shù),第一個(gè)參數(shù)是要轉(zhuǎn)換的字典對(duì)象份殿,第二個(gè)參數(shù)是要轉(zhuǎn)換的model
類的class
姿锭,因?yàn)楣差愔薪y(tǒng)一返回的都是BaseModel
類型,所以這里要調(diào)用as!
轉(zhuǎn)換成具體的子類類型伯铣。
4. 模型轉(zhuǎn)Json
JsonToModel.swift
import UIKit
class JsonToModel: BaseModel {
var id :Int!
var color:String?
var name:String?
}
//模型轉(zhuǎn)json
fileprivate func modelToJson() {
let model:JsonToModel = JsonToModel()
model.color = "red"
model.id = 100
model.name = "李四真"
let modelTostring = JsonUtil.modelToJson(model)
print(modelTostring)
}
說明:調(diào)用modelToJson(_ model:BaseModel?)
,傳入一個(gè)參數(shù)轮纫,傳入一個(gè)module
對(duì)象腔寡,返回值是一個(gè)JSON
字符串
5. 模型轉(zhuǎn)字典
JsonToModel.swift
import UIKit
class JsonToModel: BaseModel {
var id :Int!
var color:String?
var name:String?
}
//模型轉(zhuǎn)字典
fileprivate func modelTodiction() {
let model:JsonToModel = JsonToModel()
model.color = "red"
model.id = 100
model.name = "李四"
let modelTostring = JsonUtil.modelToDictionary(model)
print(modelTostring["name"] as Any)
}
說明:調(diào)用modelToDictionary(_ model:BaseModel?)
傳入一個(gè)參數(shù),傳入一個(gè)module
對(duì)象掌唾,返回值是一個(gè)字典對(duì)象放前,對(duì)于日常開發(fā)中,有時(shí)候后臺(tái)只返回一個(gè)字段糯彬,比如返回一個(gè)成功信息字段凭语,直接把返回的json
串轉(zhuǎn)換成一個(gè)字典即可,沒必要再構(gòu)建一個(gè)model
去轉(zhuǎn)換撩扒。
6. json與嵌套的模型相互轉(zhuǎn)換
CombineModel.swift
import UIKit
class Composition: BaseModel {
var aInt:Int?
var aString:String?
}
class CombineModel: BaseModel {
var aInt:Int?
var comp1:Composition?
var comp2:[Composition] = []
}
//json與嵌套的模型相互轉(zhuǎn)換
fileprivate func jsonTocombilModel() {
let model:CombineModel = CombineModel()
model.aInt = 1001
let posModel1 = Composition()
posModel1.aInt = 1
posModel1.aString = "趙六1"
let posModel2 = Composition()
posModel2.aInt = 2
posModel2.aString = "趙六2"
let posModel3 = Composition()
posModel3.aInt = 3
posModel3.aString = "趙六3"
model.comp1 = posModel1
model.comp2.append(posModel2)
model.comp2.append(posModel3)
let modeString = JsonUtil.modelToJson(model)
print(modeString)
let model2 = JsonUtil.jsonToModel(modeString, CombineModel.self)
print(model2)
}
說明:還是調(diào)用Json轉(zhuǎn)模型似扔,模型轉(zhuǎn)Json的方法
,本例子演示的是對(duì)象嵌套搓谆,對(duì)象里面可以嵌套對(duì)象炒辉,可以嵌套對(duì)象數(shù)組,平時(shí)我們開發(fā)經(jīng)常遇到這種結(jié)構(gòu)的Json串
泉手。
7. 特殊類型字段轉(zhuǎn)換黔寇,日期類型,數(shù)字類型斩萌,顏色
SpacialTypeModel.swift
import UIKit
import HandyJSON
class SpacialTypeModel: BaseModel {
var date: Date?
var decimal: NSDecimalNumber?
var url: URL?
var data: Data?
var color: UIColor?
override func mapping(mapper: HelpingMapper) {
mapper <<<
date <-- CustomDateFormatTransform(formatString: "yyyy-MM-dd")
mapper <<<
decimal <-- NSDecimalNumberTransform()
mapper <<<
url <-- URLTransform(shouldEncodeURLString: false)
mapper <<<
data <-- DataTransform()
mapper <<<
color <-- HexColorTransform()
}
}
// 特殊類型字段轉(zhuǎn)換缝裤,日期類型,數(shù)字類型颊郎,顏色
fileprivate func jsonToSpecialModel () {
let object = SpacialTypeModel()
object.date = Date()
object.decimal = NSDecimalNumber(string: "1.23423414371298437124391243")
object.url = URL(string: "https://www.aliyun.com")
object.data = Data(base64Encoded: "aGVsbG8sIHdvcmxkIQ==")
object.color = UIColor.blue
let specailModelString = JsonUtil.modelToJson(object)
print(object.toJSONString()!)
// it prints:
// {"date":"2017-09-11","decimal":"1.23423414371298437124391243","url":"https:\/\/www.aliyun.com","data":"aGVsbG8sIHdvcmxkIQ==","color":"0000FF"}
let mappedObject:SpacialTypeModel = JsonUtil.jsonToModel(specailModelString, SpacialTypeModel.self) as! SpacialTypeModel
print(mappedObject.date as Any)
}
說明:本例演示的是對(duì)于對(duì)象里含有特殊類型字段的轉(zhuǎn)換方法憋飞,主要注意點(diǎn)在構(gòu)建model
類里,我們要重寫父類mapping
方法還要引入HandyJSON
頭文件