JSONNeverDie 是一个 Swift 写的 JSON 编码、解码库,利用反射实现 JSON 到 Model 的自动映射,无需任何 parse 代码,强大而简单。
Github 地址: https://github.com/johnlui/JSONNeverDie
JSONNeverDie 可以采用“子项目”或者“源代码”两种方式引入,本人更推荐前者,更好更新。以及,非常重要的一点,也是我做纯 Swift 开发两年以来(正好到今天两年整哈哈)的最佳实践:在 Swift 时代,一切包管理工具都是累赘,手动使用 git 管理依赖的第三方工程是最好的。
多说一句,CocoaPods 这样的侵入性工具,我一开始就是拒绝的,经过这两年 Swift 翻天覆地的变化,想必各位都有了丰富的包管理工具蛋疼经历,此事就按下不表啦。
JSONNeverDie 在 2015年9月27日 发布了 0.1 版本,当时我所在的公司在开发一个 HTML5 小游戏平台,APP 中有许多的 model ,每一个都有许多的字段,写了一大堆 parse 代码的我感到一丝淡淡的忧伤:要是能够自动从 JSON 字符串映射到 model 字段就好了!加上 SwiftyJSON 有一些历史遗留问题,在处理过长非 JSON 字符时有偶发性闪退(若愚兄不要打我,来北京陪你喝酒),我便自己开发了这个 JSON 处理库。
15年底,按照计划,我离开了上家创业公司加入了住范儿,开始了为期 10 个月的“唯一程序员”生涯(10个月以后就有同伴啦)。刚开始,住范儿还处在找方向的阶段,快速开发可用原型成了我的首要工作,而当我第一次在全新 APP 中使用 JSONNeverDie 的自动映射功能的时候,我自己都要被自己感动哭了,简直太TM好用了!
后来,每做一个原型我就感动一次,有一天我突然明白,这个项目的使用示例太少了,严重阻碍了大家来用它,然后我就保留了这个信念直到今天,终于要付诸行动了,好开心!
JSONNeverDie 只有两个元数据结构:struct JSONND 和 class JSONNDModel,分别对应 JSON 对象和 Model 对象。前者为值类型,完全的 Swift Style,主要用于 json[“key”].int 这类的嵌套取值及类型转换,后者用于 Model 字段的自动映射,被迫使用了 class,继承了 NSObject。
你可以使用字符串生成 JSONND 对象以便进行取值:
let jsonFromString = JSONND(string: "{/"name/": /"JohnLui/"}")
也可以使用 Array 或 Dictionary 生成 JSONND 对象以便得到 JSON 字符串:
let jsonFromArray = JSONND(array: ["love", "you", "guys"]) let jsonFromDictionary = JSONND(dictionary: ["love": ["you": "guys"]]) print(jsonFromArray.RAWValue) print(jsonFromDictionary.RAWValue)
JSONNeverDie 之前支持从 Data 初始化,后来我想了想,这样太容易迷惑使用者。在跟 Pitaya 配合时,实际上 Pitaya 拿到的数据是 Data,首先被转换成了 String,再在 JSONNeverDie 内部被转换成 Data,最终生成 JSONND 对象,我认为这个性能损失是非常有价值的。我时刻谨记:代码是写给人看的,只是恰好能运行。同样,我的库是写给人用的,不是写来让机器跑的。
我们使用上面生成的 jsonFromString
对象作为数据源,先定义 Model 类:
class People: JSONNDModel{ var name = "" }
然后直接使用 JSONND 对象初始化这个类:
let people = People(JSONNDObject: json) print(people.name) // get "JohnLui"
That’s it!
class Good : JSONNDModel{ var des = "" override init(JSONNDObject json: JSONND) { // 记得要先调用父类的初始化 // 自动映射实际上是在这一步完成的 super.init(JSONNDObject: json) // 再获取你想要的字段并赋值 // 此时可随意修改 Model 类 self.des = json["description"].stringValue } }
JSON 标准支持四种基础类型和两种结构类型:
JSON can represent four primitive types (strings, numbers, booleans,
and null) and two structured types (objects and arrays).
这反映在 Swift 中就是 String、Int、Double、Bool、nil、Dictionary、Array。
那就是要有初始值。有了初始值才会真正的分配内存空间,才能做到类型探测,才能自动映射。
能怎么办?手动搞呗:
class TestModel: JSONNDModel{ var string = "" var double = 0.0 var int = 0 var array_values = [Int]() override init(JSONNDObject json: JSONND) { // 完成 string double int 三个属性的自动映射 super.init(JSONNDObject: json) // 手动完成数组赋值 for i in json["array_values"].arrayValue { self.array_values.append(i.intValue) } } }
手动搞,没问题,还支持嵌套对象数组呢:
class TestModel: JSONNDModel{ var string = "" var double = 0.0 var int = 0 // 普通数组 var array_values = [Int]() // 文艺数组 var array = [ModelOnlyOneKey]() // 二逼...不对,是普通对象 var hey: Hey! override init(JSONNDObject json: JSONND) { super.init(JSONNDObject: json) for i in json["array_values"].arrayValue { self.array_values.append(i.intValue) } for i in json["array"].arrayValue { self.array.append(ModelOnlyOneKey(JSONNDObject: i)) } self.hey = Hey(JSONNDObject: json["hey"]) } }