【KakaJSON手册】04_JSON转Model_04_值过滤
在KakaJSON手册的第2篇文章中提过:由于JSON格式能表达的数据类型是比较有限的,所以服务器返回的JSON数据有时无法自动转换成客户端想要的数据类型
- 比如客户端想要的是Date类型,服务器返回的可能是字符串
"2018-08-08 08:08:08.888"
或者"2018/08/08 08:08:08.888"
- 像上述情况,KakaJSON内部是无法自动转换的,但提供了值过滤机制,允许开发者对JSON值进行自定义处理
日期处理
// 这2个DateFormatter仅仅为了举例子而写的,具体细节根据自己需求而定
private let date1Fmt: DateFormatter = {
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
return fmt
}()
private let date2Fmt: DateFormatter = {
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
return fmt
}()
struct Student: Convertible {
var date1: Date?
var date2: NSDate?
// 实现kj_modelValue方法
// 会传入属性`property`以及这个属性对应的JSON值`jsonValue`
// 返回值是你希望最后设置到模型属性上的值
// 如果返回`jsonValue`,代表不做任何事,交给KakaJSON内部处理
// 如果返回`nil`,代表忽略这个属性,KakaJSON不会给这个属性设值(属性会保留它的默认值)
func kj_modelValue(from jsonValue: Any?, _ property: Property) -> Any? {
switch property.name {
// 如果jsonValue是字符串,就直接转成Date
case "date1": return (jsonValue as? String).flatMap(date1Fmt.date)
// 如果jsonValue是字符串,就直接转成Date
// 由于NSDate与Date之间是可以桥接转换的,所以返回Date给NSDate属性也是没有问题的
case "date2": return (jsonValue as? String).flatMap(date2Fmt.date)
default: return jsonValue
}
}
}
let date1 = "2008-09-09"
let date2 = "2011-11-12 14:20:30.888"
let json: [String: Any] = [
"date1": date1,
"date2": date2
]
let student = json.kj.model(Student.self)
// 将Date\NSDate转回字符串进行比较
XCTAssert(student.date1.flatMap(date1Fmt.string) == date1)
XCTAssert(student.date2.flatMap(date2Fmt.string) == date2)
不确定类型
// 有时候服务器返回的某个字段的内容类型可能是不确定的
// 客户端可以先标记为Any类型或者AnyObject类型或者协议类型等不确定类型
struct Person: Convertible {
var name: String = ""
var pet: Any?
func kj_modelValue(from jsonValue: Any?, _ property: Property) -> Any? {
// 如果不是`pet`属性,就按照默认处理
if property.name != "pet" { return jsonValue }
// 如果是`pet`属性,并且`jsonValue`是个字典,就转换为`Dog`模型实例
// 具体判断逻辑可以根据实际开发需求而定
return (jsonValue as? [String: Any])?.kj.model(Dog.self)
}
}
struct Dog: Convertible {
var name: String = ""
var weight: Double = 0.0
}
let json: [String: Any] = [
"name": "Jack",
"pet": ["name": "Wang", "weight": 109.5]
]
let person = json.kj.model(Person.self)
XCTAssert(person.name == "Jack")
let pet = person.pet as? Dog
XCTAssert(pet?.name == "Wang")
XCTAssert(pet?.weight == 109.5)
/*---------------------------------------------*/
class Book: Convertible {
var name: String = ""
var price: Double = 0.0
required init() {}
}
struct Person: Convertible {
var name: String = ""
// [AnyObject]、[Convertible]、NSArray、NSMutableArray
var books: [Any]?
func kj_modelValue(from jsonValue: Any?,
_ property: Property) -> Any? {
if property.name != "books" { return jsonValue }
// if books is `NSMutableArray`, neet convert `Array` to `NSMutableArray`
// because `Array` to `NSMutableArray` is not a bridging conversion
return (jsonValue as? [Any])?.kj.modelArray(Book.self)
}
}
let name = "Jack"
let books = [
(name: "Fast C++", price: 666),
(name: "Data Structure And Algorithm", price: 1666)
]
let json: [String: Any] = [
"name": name,
"books": [
["name": books[0].name, "price": books[0].price],
["name": books[1].name, "price": books[1].price]
]
]
let person = json.kj.model(Person.self)
XCTAssert(person.name == name)
XCTAssert(person.books?.count == books.count)
let book0 = person.books?[0] as? Book
XCTAssert(book0?.name == books[0].name)
XCTAssert(book0?.price == Double(books[0].price))
let book1 = person.books?[1] as? Book
XCTAssert(book1?.name == books[1].name)
XCTAssert(book1?.price == Double(books[1].price))
其他例子
struct Student: Convertible {
var age: Int = 0
var name: String = ""
func kj_modelValue(from jsonValue: Any?, _ property: Property) -> Any? {
switch property.name {
// 如果`age`属性的`jsonValue`是整数,就加上5
case "age": return (jsonValue as? Int).flatMap { $0 + 5 }
// 如果`name `属性的`jsonValue`是字符串,就在前面加上`kj_`
case "name": return (jsonValue as? String).flatMap { "kj_" + $0 }
default: return jsonValue
}
}
}
let json: [String: Any] = [
"age": 10,
"name": "Jack"
]
let student = json.kj.model(Student.self)
XCTAssert(student.age == 15)
XCTAssert(student.name == "kj_Jack")
其他实现思路
// 关于值过滤、自定义值处理的逻辑,也可以在模型转换完毕之后进行
struct Student: Convertible {
var age: Int = 0
var name: String = ""
// 实现`kj_didConvertToModel`方法,在这里修改转换之后的属性值
mutating func kj_didConvertToModel(from json: [String: Any]) {
age += 5
name = "kj_" + name
}
}
let json: [String: Any] = [
"age": 10,
"name": "Jack"
]
let student = json.kj.model(Student.self)
XCTAssert(student.age == 15)
XCTAssert(student.name == "kj_Jack")
最后的提示
kj_modelValue
也支持ConvertibleConfig
配置,用法类似于kj_modelKey
,参考第三篇文章
【KakaJSON手册】04_JSON转Model_04_值过滤的更多相关文章
- 【KakaJSON手册】01_JSON转Model_01_基本用法
在iOS开发中,后台返回的数据大多是JSON格式,对应地会被网络框架层解析成Swift中的Dictionary.Array.由于数据类型的复杂.字段的繁多,直接使用Dictionary.Array会比 ...
- 【KakaJSON手册】06_Model转JSON
前面的文章介绍了如何利用KakaJSON进行JSON转Model,从这篇文章开始介绍如何将Model转成JSON 生成JSON和JSONString struct Car: Convertible { ...
- 【KakaJSON手册】02_JSON转Model_02_数据类型
由于JSON格式的能表达的数据类型是比较有限的,所以服务器返回的JSON数据有时无法自动转换成客户端想要的数据类型. 比如服务器返回的时间可能是个毫秒数1565480696,但客户端想要的是Date类 ...
- 【KakaJSON手册】03_JSON转Model_03_key处理
有时候,服务器返回的JSON数据的key跟客户端模型的属性名可能不一致,比如客户端遵守驼峰规范叫做nickName,而服务器端返回的JSON可能叫做nick_name.这时候为了保证数据转换成功,就需 ...
- 如何在django-filter中用choice field 的 value 值过滤对象
如果我们有这样一个model: class IPInfoModel(models.Model): TYPE_INTRANET = 1 TYPE_INTERNET = 2 IP_TYPES = ( (T ...
- 【KakaJSON手册】05_JSON转Model_05_动态模型
在上一篇文章中提到:有时候服务器返回的某个字段的内容类型可能是不确定的 当时给出的解决方案是实现kk_modelValue或者kk_didConvertToModel方法,根据实际需求自定义JSON的 ...
- 【KakaJSON手册】08_其他用法
除了完成JSON和Model的转换之外,KakaJSON内部还有很多实用的功能,有些也开放为public接口了 遍历属性 struct Cat { var age: Int = 0 let name: ...
- 【KakaJSON手册】07_Coding_归档_解档
KakaJSON可以只用一行代码将常用数据进行归档\解档 后面代码中会用到 file 文件路径 // 文件路径(String或者URL都可以) let file = "/Users/mj/D ...
- Python数据科学手册-Pandas:数据取值与选择
Numpy数组取值 切片[:,1:5], 掩码操作arr[arr>0], 花哨的索引 arr[0, [1,5]],Pandas的操作类似 Series数据选择方法 Series对象与一维Nump ...
随机推荐
- python文件下载
1. 场景描述 刚好总结Java项目的web文件下载(附方案及源码配置),想起python项目也有用到文件下载,就也介绍下吧. 2. 解决方案 使用python的第三方组件Flask来实现文件下载功能 ...
- 【题解】埃及分数-C++
Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一个分数a/ ...
- 如果通过脚本来关闭程序-linux
正常情况下在linux关闭一个程序最好是走正常的关闭流程,不要直接杀死进程,这样程序的稳定性确实会收到影响,但是如果想通过脚本来关闭程序正常情况下比较困难的,我便采取了这种暴力的方法-直接杀死进程. ...
- NOIp2018普及组T3暨洛谷P5017 摆渡车:题解
题目链接:https://www.luogu.org/problemnew/show/P5017 emm,这次的真的不简单的,T3比T4难? 醉了... 蒟蒻肯定没有其他大佬讲的好啊,但肯定尽力,真的 ...
- 将web工程署到Linux简单实现
1,将数据库文件导出并导入到Linux下的数据库中 2,将数据库连接池的连接IP改为Linux所在服务器的 3,将工程文件以war包形式导出 4,利用secureCRT,Xshell等工具远程连接Li ...
- 用tcp协议实现一个并发的socketserver 进行密文登录
先在客户端进行摘要,客户端把用户名作为盐. 然后在服务端进行二次摘要,用固定的盐(不能让别人知道你的盐是什么),然后存到文件中,密文存储.或者和文件中的密文对比. 这样即使在网络上用户信息被截获,和存 ...
- JDK(Windows)
百度云:链接:http://pan.baidu.com/s/1dEEsIUd 密码:15cn 官网下载网址:http://www.oracle.com/technetwork/java/jav ...
- JSON的简单使用之提取多层嵌套的JSON(C#)
JSON.NET(http://json.codeplex.com/)使用来将.NET中的对象转换为JSON字符串(序列化?),或者将JSON字符串转换为.NET中已有类型的对象(反序列化?) 反序列 ...
- docker跨主机通信扁平化网络的设计与实现
端口映射.ovs. fannel,weave 1.使用网桥实现跨主机容器连接 使用Open vSwitch实现跨主机容器连接
- spark 源码分析之八--Spark RPC剖析之TransportContext和TransportClientFactory剖析
spark 源码分析之八--Spark RPC剖析之TransportContext和TransportClientFactory剖析 TransportContext 首先官方文档对Transpor ...