有时候,服务器返回的JSON数据的key跟客户端模型的属性名可能不一致,比如客户端遵守驼峰规范叫做
nickName
,而服务器端返回的JSON可能叫做nick_name
。这时候为了保证数据转换成功,就需要对模型属性名和JSON的key进行相应的映射。
1.最基本的用法
struct Person: Convertible {
var nickName: String = ""
var mostFavoriteNumber: Int = 0
var birthday: String = ""
// 实现kj_modelKey方法
// 会传入模型的属性`property`作为参数,返回值就是属性对应的key
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// 根据属性名来返回对应的key
switch property.name {
// 模型的`nickName`属性 对应 JSON中的`nick_name`
case "nickName": return "nick_name"
// 模型的`mostFavoriteNumber `属性 对应 JSON中的`most_favorite_number `
case "mostFavoriteNumber": return "most_favorite_number"
// 模型剩下的其他属性,直接用属性名作为JSON的key(属性名和key保持一致)
default: return property.name
}
}
}
let nick_name = "ErHa"
let most_favorite_number = 666
let birthday = "2011-10-12"
let json: [String: Any] = [
"nick_name": nick_name,
"most_favorite_number": most_favorite_number,
"birthday": birthday
]
let person = json.kj.model(Person.self)
print("nickName:\(person.nickName) mostFavoriteNumber:\(person.mostFavoriteNumber) birthday:\(person.birthday)")
// nickName:ErHa mostFavoriteNumber:666 birthday:2011-10-12
2.驼峰 -> 下划线
struct Person: Convertible {
var nickName: String = ""
var mostFavoriteNumber: Int = 0
var birthday: String = ""
// 实现kj_modelKey方法
// 会传入模型的属性`property`作为参数,返回值就是属性对应的key
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// 由于开发中可能经常遇到`驼峰`映射`下划线`的需求,KakaJSON已经内置了处理方法
// 直接调用字符串的underlineCased方法就可以从`驼峰`转为`下划线`
// `nickName` -> `nick_name`
return property.name.kj.underlineCased()
}
}
let nick_name = "ErHa"
let most_favorite_number = 666
let birthday = "2011-10-12"
let json: [String: Any] = [
"nick_name": nick_name,
"most_favorite_number": most_favorite_number,
"birthday": birthday
]
let person = json.kj.model(Person.self)
print("nickName:\(person.nickName) mostFavoriteNumber:\(person.mostFavoriteNumber) birthday:\(person.birthday)")
// nickName:ErHa mostFavoriteNumber:666 birthday:2011-10-12
3.下划线 -> 驼峰
struct Person: Convertible {
var nick_name: String = ""
var most_favorite_number: Int = 0
var birthday: String = ""
// KakaJSON也给字符串内置了camelCased方法,可以由`下划线`转为`驼峰`
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// `nick_name` -> `nickName`
return property.name.kj.camelCased()
}
}
let nickName = "ErHa"
let mostFavoriteNumber = 666
let birthday = "2011-10-12"
let json: [String: Any] = [
"nickName": nickName,
"mostFavoriteNumber": mostFavoriteNumber,
"birthday": birthday
]
let person = json.kj.model(Person.self)
print("nick_name:\(person.nick_name) most_favorite_number:\(person.most_favorite_number) birthday:\(person.birthday)")
// nick_name:ErHa most_favorite_number:666 birthday:2011-10-12
4. 继承
// 子类可以继承父类的实现
class Person: Convertible {
var nickName: String = ""
required init() {}
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// `nickName` -> `nick_ame`
return property.name.kj.underlineCased()
}
}
class Student: Person {
var mathScore: Int = 0
// Person的kj_modelKey会继承下来给Student使用
// `mathScore` -> `math_score`
}
let nick_ame = "Jack"
let math_score = 96
let json: [String: Any] = ["nick_name": nick_ame, "math_score": math_score]
let student = json.kj.model(Student.self)
print("nickName:\(student.nickName) mathScore:\(student.mathScore)")
// nickName:Jack mathScore:96
5.重写
// 子类可以重写父类的kj_modelKey方法,在父类实现的基础上加一些自己的需求
class Person: Convertible {
var name: String = ""
required init() {}
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// `name` -> `_name_`
return property.name == "name" ? "_name_" : property.name
}
}
class Student: Person {
var score: Int = 0
override func kj_modelKey(from property: Property) -> ModelPropertyKey {
// 调用了`super.kj_modelKey`,在父类的基础上加了对`score`的处理
// `score` -> `_score_`,`name` -> `_name_`
return property.name == "score" ? "_score_" : super.kj_modelKey(from: property)
}
}
let name = "Jack"
let score = 96
let json: [String: Any] = ["_name_": name, "_score_": score]
let student = json.kj.model(Student.self)
print("name:\(student.name) score:\(student.score)")
// name:Jack score:96
6.重写 + 覆盖
// 子类可以重写父类的kj_modelKey方法,并完全覆盖父类的实现
class Person: Convertible {
var name: String = ""
required init() {}
func kj_modelKey(from property: Property) -> ModelPropertyKey {
// `name` -> `_name_`
return property.name == "name" ? "_name_" : property.name
}
}
class Student: Person {
var score: Int = 0
override func kj_modelKey(from property: Property) -> ModelPropertyKey {
// 这里并没有调用`super. kj_modelKey`
// 因此`score` -> `_score_`,`name` -> `name`
return property.name == "score" ? "_score_" : property.name
}
}
let name = "Jack"
let score = 96
let json: [String: Any] = ["name": name, "_score_": score]
let student = json.kj.model(Student.self)
print("name:\(student.name) score:\(student.score)")
// name:Jack score:96
7.全局配置
// 一旦有需要进行`驼峰` -> `下划线`的映射,有可能整个项目的所有模型都需要进行映射,毕竟整个项目的命名规范是统一的
// 假设项目中有100多个模型,那么就需要实现100多次`kj_modelKey`方法,调用100多次underlineCased方法
// KakaJSON内置了全局配置机制,可以1次配置,就能适用于所有的模型(不管是struct还是class,只要是遵守Convertible协议的模型)
// 全局配置整个项目中只需要配置1次,建议在AppDelegate的didFinishLaunching中配置1次即可
ConvertibleConfig.setModelKey { property in
property.name.kj.underlineCased()
}
// ConvertibleConfig.setModelKey { $0.name.kj.underlineCased() }
class Person: Convertible {
var nickName: String = ""
required init() {}
}
let nick_ame = "Jack"
let json: [String: Any] = ["nick_name": nick_ame]
let person = json.kj.model(Person.self)
print("name:\(person.nickName)")
// name:Jack
8.复杂的key映射
struct Toy: Convertible {
var price: Double = 0.0
var name: String = ""
}
struct Dog: Convertible {
var name: String = ""
var age: Int = 0
var nickName: String?
var toy: Toy?
func kj_modelKey(from property: Property) -> ModelPropertyKey {
switch property.name {
// 对应dog["toy"]
case "toy": return "dog.toy"
// 对应data[1]["dog"]["name"]
case "name": return "data.1.dog.name"
// 会按顺序映射数组中的每一个key,直到成功为止
// 先映射`nickName`,如果失败再映射`nick_name`
// 如果失败再映射`dog["nickName"]`,如果失败再映射`dog["nick_name"]`
case "nickName": return ["nickName", "nick_name", "dog.nickName", "dog.nick_name"]
default: return property.name
}
}
}
let name = "Larry"
let age = 5
let nickName1 = "Jake1"
let nickName2 = "Jake2"
let nickName3 = "Jake3"
let nickName4 = "Jake4"
let toy = (name: "Bobbi", price: 20.5)
let json: [String: Any] = [
"data": [10, ["dog" : ["name": name]]],
"age": age,
"nickName": nickName1,
"nick_name": nickName2,
"dog": [
"nickName": nickName3,
"nick_name": nickName4,
"toy": ["name": toy.name, "price": toy.price]
]
]
let dog = json.kj.model(Dog.self)
print("name:\(dog.name) age:\(dog.age) nickName:\(dog.nickName!) toy:\(dog.toy!)")
// name:Larry age:5 nickName:Jake1 toy:Toy(price: 20.5, name: "Bobbi")
Swift 字典转模型(KakaJSON) ---1.基本用法
Swift 字典转模型(KakaJSON) ---2.数据类型
Swift 字典转模型(KakaJSON) ---4.动态模型
Swift KakaJSON 05.---模型转字典
Swift KakaJSON 06.---Coding/归档/解档
网友评论