在iOS开发中,后台返回的数据大多是JSON格式,对应地会被网络框架层解析成Swift中的Dictionary、Array。由于数据类型的复杂、字段的繁多,直接使用Dictionary、Array会比较麻烦,比如items[0]["user"]["name"]这样的使用方式,非常不友善,而且没有智能语法提示。所以很多时候会考虑将JSON转换成Model之后再进行操作,会友善很多,比如items[0].user.name。
1.最简单的Model
// ① 让模型类型遵守`Convertible`协议
struct Cat: Convertible {
var name: String = ""
var weight: Double = 0.0
}
// json也可以是NSDictionary、NSMutableDictionary类型
let json: [String: Any] = [
"name" : "Miaomiao",
"weight" : 6.66
]
// ② 直接调用json的model方法,传入模型类型,返回模型实例
let cat = json.kj.model(Cat.self)
//let cat = model(from: json, Cat.self)
print("name:\(cat.name), weight:\(cat.weight)")
// name:Miaomiao, weight:6.66
2.Class类型
class Cat: Convertible {
var name: String = ""
var weight: Double = 0.0
// 由于Swift初始化机制的原因,`Convertible`协议强制要求实现init初始化器
// 这样框架内部才可以完整初始化一个实例
required init() {}
}
let json: [String: Any] = [
"name" : "老斑",
"weight" : 6.66
]
let cat = json.kj.model(Cat.self)
print("name:\(cat.name), weight:\(cat.weight)")
// name:老斑, weight:6.66
// 继承自NSObject的类也是一样的用法
class Person: NSObject, Convertible {
var name: String = ""
var age: Int = 0
// 由于NSObject内部已经有init,因此Person算是重载init,需再加上`override`
required override init() {}
}
let json: [String: Any] = [
"name" : "李连杰",
"age" : 67
]
let person = json.kj.model(Person.self)
print("name:\(person.name), age:\(person.age)")
// name:李连杰, age:67
struct Dog: Convertible {
var weight: Double = 0.0
var name: String = ""
// 由于编译器自动帮结构体类型生成了一个init初始化器
// 所以不需要自己再实现init初始化器
}
struct Pig: Convertible {
var weight: Double
var name: String
// 如果没有在定义属性的同时指定初始值,编译器是不会为结构体生成init初始化器的
// 所以需要自己实现init初始化器
init() {
name = ""
weight = 0.0
}
}
3.继承
class Person: Convertible {
var name: String = ""
var age: Int = 0
// 由于NSObject内部已经有init,因此Person算是重载init,需再加上`override`
required init() {}
}
class Student: Person {
var score: Int = 0
var no: String = ""
}
let json: [String: Any] = [
"name": "jack",
"age": 18,
"score": 98,
"no": "9527"
]
let student = json.kj.model(Student.self)
print("name:\(student.name), age:\(student.age), score:\(student.score), no:\(student.no)")
// name:jack, age:18, score:98, no:9527
4.let属性
struct Cat: Convertible {
// 测试表明:在真机release模式下,对数字类型的let限制比较严格
// 值虽然修改成功了(可以打印Cat结构体发现weight已经改掉了),但get出来还是0.0
// 所以建议使用`private(set) var`取代`let`
private(set) var weight: Double = 0.0
let name: String = ""
}
let json: [String: Any] = [
"name" : "Miaomiao",
"weight" : 6.66
]
let cat = json.kj.model(Cat.self)
print("name:\(cat.name), weight:\(cat.weight)")
// name:Miaomiao, weight:6.66
5. JSONString
struct Cat: Convertible {
var weight: Double = 0.0
var name: String = ""
}
// jsonString也可以是NSString、NSMutableString类型
let jsonString = """
{
"name": "Miaomiao",
"weight": 6.66
}
"""
let cat = jsonString.kj.model(Cat.self)
guard let cat1 = cat else { // guard let 守护
return
}
print("name:\(cat1.name), weight:\(cat1.weight)")
// name:Miaomiao, weight:6.66
6. JSONData
struct Cat: Convertible {
var weight: Double = 0.0
var name: String = ""
}
// jsonData也可以是NSData、NSMutableData类型
let jsonData = """
{
"name": "Miaomiao",
"weight": 6.66
}
""".data(using: .utf8)!
let cat = jsonData.kj.model(Cat.self)
guard let cat1 = cat else {
return
}
print("name:\(cat1.name), weight:\(cat1.weight)")
// name:Miaomiao, weight:6.66
7.Model嵌套1
// 让需要进行转换的模型都遵守`Convertible`协议
struct Book: Convertible {
var name: String = ""
var price: Double = 0.0
}
struct Car: Convertible {
var name: String = ""
var price: Double = 0.0
}
struct Dog: Convertible {
var name: String = ""
var age: Int = 0
}
struct Person: Convertible {
var name: String = ""
var car: Car?
var books: [Book]?
var dogs: [String: Dog]?
}
let json: [String: Any] = [
"name": "Jack",
"car": ["name": "BMW7", "price": 105.5],
"books": [
["name": "Fast C++", "price": 666.6],
["name": "Data Structure And Algorithm", "price": 1666.6]
],
"dogs": [
"dog0": ["name": "Larry", "age": 5],
"dog1": ["name": "ErHa", "age": 2]
]
]
let person = json.kj.model(Person.self)
guard let car = person.car,
let books = person.books,
let dogs = person.dogs else {
return
}
print("name:\(person.name), car:\(car)")
for book: Book in books {
print("book:\(book)")
}
for (key, value) in dogs {
print("key:\(key) value:\(value)")
}
/*
name:Jack, car:Car(name: "BMW7", price: 105.5)
book:Book(name: "Fast C++", price: 666.6)
book:Book(name: "Data Structure And Algorithm", price: 1666.6)
key:dog0 value:Dog(name: "Larry", age: 5)
key:dog1 value:Dog(name: "ErHa", age: 2)
*/
8.Model嵌套2
struct Car: Convertible {
var name: String = ""
var price: Double = 0.0
}
class Dog: Convertible {
var name: String = ""
var age: Int = 0
required init() {}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
struct Person: Convertible {
var name: String = ""
// 如果你的模型有默认值,KakaJSON内部不会再创建新的模型
// 会直接重复利用你创建的模型,节省内存分配和初始化的开销
var car: Car = Car(name: "Bently", price: 106.5)
var dog: Dog = Dog(name: "Larry", age: 5)
}
let json: [String: Any] = [
"name": "Jake",
"car": ["price": 305.6],
"dog": ["name": "Wangwang"]
]
let person = json.kj.model(Person.self)
print("name:\(person.name), car:\(person.car)")
print("dog: ----> name:\(person.dog.name) age:\(person.dog.age)")
/*
name:Jake, car:Car(name: "Bently", price: 305.6)
dog: ----> name:Wangwang age:5
*/
9.泛型
struct NetRespones<Element>: Convertible {
let data: Element? = nil
let msg: String = ""
private(set) var code: Int = 0
}
struct User: Convertible {
let id: String = ""
let nickName: String = ""
}
struct Goods: Convertible {
private(set) var price: CGFloat = 0.0
let name: String = ""
}
let json1 = """
{
"data": {"nickName": "KaKa", "id": 213234234},
"msg": "Success",
"code" : 200
}
"""
let response = json1.kj.model(NetRespones<User>.self)
guard let response1 = response else {
return
}
print("response: msg: \(response1.msg) code:\(response1.code) data:\(response1.data ?? User())")
// response: msg: Success code:200 data:User(id: "213234234", nickName: "KaKa")
10.Model数组
struct Car: Convertible {
var name: String = ""
var price: Double = 0.0
}
// json数组可以是Array<[String: Any]>、NSArray、NSMutableArray
let json: [[String: Any]] = [
["name": "Benz", "price": 98.6],
["name": "Bently", "price": 305.7],
["name": "Audi", "price": 64.7]
]
// 调用json数组的modelArray方法即可
let cars = json.kj.modelArray(Car.self)
for car: Car in cars {
print("car: \(car)")
}
print("----------------------------")
for (index, value) in cars.enumerated() {
print("index: \(index) value: \(value)")
}
/*
car: Car(name: "Benz", price: 98.6)
car: Car(name: "Bently", price: 305.7)
car: Car(name: "Audi", price: 64.7)
----------------------------
index: 0 value: Car(name: "Benz", price: 98.6)
index: 1 value: Car(name: "Bently", price: 305.7)
index: 2 value: Car(name: "Audi", price: 64.7)
*/
11. Convert
// 如果你想把JSON数据转换到原本已经创建好的模型实例上,可以使用convert方法
struct Cat: Convertible {
var name: String = ""
var weight: Double = 0.0
}
let json: [String: Any] = [
"name": "Miaomiao",
"weight": 6.66
]
var cat = Cat()
// .kj_m是.kj的mutable版本,牵扯到修改实例本身都是.kj_m开头
cat.kj_m.convert(from: json)
print("name: \(cat.name) weight\(cat.weight)")
// name: Miaomiao weight6.66
12. 监听
// 有时候可能想在JSON转模型之前、之后做一些额外的操作
// KakaJSON会在JSON转模型之前调用模型的kj_willConvertToModel方法
// KakaJSON会在JSON转模型之后调用模型的kj_didConvertToModel方法
struct Car: Convertible {
var name: String = ""
var age: Int = 0
func kj_willConvertToModel(from json: [String : Any]) {
print("Car - kj_willConvertToModel")
}
mutating func kj_didConvertToModel(from json: [String : Any]) {
print("Car - kj_didConvertToModel")
}
}
let json: [String: Any] = [
"name": "Benz",
"age": 100
]
var car = json.kj.model(Car.self)
print("name: \(car.name) age: \(car.age)")
/*
Car - kj_willConvertToModel
Car - kj_didConvertToModel
name: Benz age: 100
*/
/*************************************************************/
// 同样也支持类
class Person: Convertible {
var name: String = ""
var age: Int = 0
required init() {}
func kj_willConvertToModel(from json: [String: Any]) {
print("Person - kj_willConvertToModel")
}
func kj_didConvertToModel(from json: [String: Any]) {
print("Person - kj_didConvertToModel")
}
}
class Student: Person {
var score: Int = 0
override func kj_willConvertToModel(from json: [String : Any]) {
// 如果有必要的话,可以调用super的实现
super.kj_willConvertToModel(from: json)
print("Student - kj_willConvertToModel")
}
override func kj_didConvertToModel(from json: [String: Any]) {
// 如果有必要的话,可以调用super的实现
super.kj_didConvertToModel(from: json)
print("Student - kj_didConvertToModel")
}
}
let json: [String: Any] = [
"name" : "jack",
"age" : 10,
"score" : 100
]
let student = json.kj.model(Student.self)
print("name:\(student.name), age:\(student.age) score:\(student.score)")
/*
Person - kj_willConvertToModel
Student - kj_willConvertToModel
Person - kj_didConvertToModel
Student - kj_didConvertToModel
name:jack, age:10 score:100
*/
Swift 字典转模型(KakaJSON) ---2.数据类型
Swift 字典转模型(KakaJSON) ---3.key处理
Swift 字典转模型(KakaJSON) ---4.动态模型
Swift KakaJSON 05.---模型转字典
Swift KakaJSON 06.---Coding/归档/解档
网友评论