在iOS开发中,后台返回的数据大多是JSON格式,对应地会被网络框架层解析成Swift中的Dictionary、Array。由于数据类型的复杂、字段的繁多,直接使用Dictionary、Array会比较麻烦,比如items[0]["user"]["name"]这样的使用方式,非常不友善,而且没有智能语法提示。所以很多时候会考虑将JSON转换成Model之后再进行操作,会友善很多,比如items[0].user.name

  • Swift内置了一套Codable机制,可以用于JSON转Model。对于一些简单的模型结构,还是挺好用,但一旦牵扯到复杂的模型结构、一些个性化的需求(比如KeyMapping、类型不匹配时的转换处理、自定义解析规则等),Codable就无法友善地完成任务了。
  • 为了解决上述问题,我编写了一套纯Swift实现的JSON与Model互相转换的框架:KakaJSON,本人非常喜欢龙珠,框架取名自Kaka Rotto(卡卡罗特,孙悟空)。基于之前编写过OC版本的JSON\Model转换框架MJExtension的经验,绕过了很多坑,编写过程也比较顺利。对外提供了一些友善易用、可扩展的接口,内置了Metedata缓存等机制,加快转换速度。
  • 本教程是为了让大家能够快速上手KakaJSON的使用,挖掘它内部的各种功能,发挥它的最大威力。未来也可以会推出一些源码分析的文章。

最简单的Model

import KakaJSON

// ① 让模型类型遵守`Convertible`协议
struct Cat: Convertible {
    var weight: Double = 0.0
    var name: String = ""
}

let json: [String: Any] = [
    "weight": "Miaomiao",
    "name": 6.66
]

// ② 直接调用json的model方法,传入模型类型,返回模型实例
let cat = json.kk.model(Cat.self)
print(cat?.name) // Miaomiao
print(cat?.weight) // 6.66

// 或者也可以调用一个全局函数来完成字典转模型
let cat2 = model(from: json, Cat.self)

Any.Type

// 有时类型可能是个变量,比如
var type: Any.Type = Cat.self

// 调用带有anyType参数的方法即可
// 由于传入的类型是Any.Type,所以返回值类型是Any,到时根据需求强制转换成自己想要的类型
let cat = json.kk.model(anyType: type) as? Cat

// 或者调用全局函数
let cat2 = model(from: json, anyType: type) as? Cat

JSONString

// jsonString可以是String、NSString、NSMutableString
let jsonString: String = """
{
    "name": "Miaomiao",
    "weight": 6.66
}
"""

// 跟JSON的用法是一样的
let cat = jsonString.kk.model(Cat.self)
let cat2 = model(from: jsonString, Cat.self)
var type: Any.Type = Cat.self
let cat3 = jsonString.kk.model(anyType: type) as? Cat
let cat4 = model(from: jsonString, anyType: type) as? Cat

Model嵌套

// 让需要进行转换的模型都遵守`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.kk.model(Person.self)
print(person?.car?.name) // BMW7
print(person?.books?[1].name) // Data Structure And Algorithm
print(person?.dogs?["dog0"]?.name) // Larry

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.kk.modelArray(Car.self)
print(cars?[1].name) // Bently

// 同样的还有其他方式
let cars2 = modelArray(from: json, Car.self)
var type: Any.Type = Car.self
let cars3 = json.kk.modelArray(anyType: type) as? [Car]
let cars4 = modelArray(from: json, anyType: Car.self) as? [Car]

// 另外,jsonString转为Model数组,也是如此简单
let jsonString = "...."
let cars5 = jsonString.kk.modelArray(Car.self)
let cars6 = modelArray(from: jsonString, Car.self)
let cars7 = jsonString.kk.modelArray(anyType: type) as? [Car]
let cars8 = modelArray(from: jsonString, anyType: Car.self) as? [Car]

【KakaJSON手册】01_JSON转Model_01_基本用法的更多相关文章

  1. Linux-查看C语言手册及man的特殊用法

    man命令可以查看c语言库函数的函数原型, 比如 $ man malloc 如果显示 "No manual entry for malloc", 则需要安装 "man-p ...

  2. shell脚本学习之Bash shell 里各种括号的用法

    今天在 SegmentFault 上看到又有人问起关于Shell里各种括号的问题.对于很多玩Shell的人,括号是个很尴尬的问题,用起来没问题,说起来不明白,我在这里总结一下Bash Shell几种括 ...

  3. Linux常用命令手册

    Linux常用命令手册 NO 分类 PS1 命令名 用法及参数 功能注解 对应章节 1 文件管理 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件     文件管理 # ls ls ...

  4. linux中find命令高级用法

    前言 在<Linux中的文件查找技巧>一文中,我们已经知道了文件查找的基本方法,今天我们介绍find命令的一些高级使用技巧.它能满足我们一些更加复杂的需求. 查找空文件或空目录 有时候需要 ...

  5. MAN 手册各章节功能介绍及快捷键键位整理

    前言   Man 手册页(Manua pages ,缩写man page) 是在linux操作系统在线软件文档的一种普遍形式.内容包括计算机程序库和系统调用等命令的帮助手册. 手册页是用troff排版 ...

  6. Delete,Update与LEFT Join

    UPDATE:UPDATE A SET ApproverID=NULL FROM [SH_MaterialApplyBuyBill] A LEFT JOIN [SH_MaterialApplyBuyB ...

  7. (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. shell中括号的使用

    在这里我想说的是几种shell里的小括号,大括号结构和有括号的变量,命令的用法,如下: 1.${var} 2.$(cmd) 3.()和{} 4.${var:-string},${var:+string ...

  9. php代码效率测试

    对于一个被加载的页面,而遇到会卡的原因 ,代码量大,为了减少一句话分析,就采用分段式判断. 从php手册了解到,使用microtime函数,具体方法可参见php手册对这函数的用法 定义get_exec ...

  10. sublime配置全攻略

    大家好,今天给大家分享一款编辑器:sublime text2     我用过很多编辑器, EditPlus.EmEditor.Notepad++.Notepad2.UltraEdit.Editra.V ...

随机推荐

  1. Win10 连接L2TP VPN 失败解决方法

    Win10 连接L2TP VPN 失败解决方法 iOS系统不知道在什么时候,已经不支持PPTP VPN.偶尔的机会刚好看到github上的一键式VPN服务器部署脚本setup-ipsec-vpn,就在 ...

  2. 【原】Spark之机器学习(Python版)(一)——聚类

      kmeans聚类相信大家都已经很熟悉了.在Python里我们用kmeans通常调用Sklearn包(当然自己写也很简单).那么在Spark里能不能也直接使用sklean包呢?目前来说直接使用有点困 ...

  3. Django搭建简易博客

    Django简易博客,主要实现了以下功能 连接数据库 创建超级用户与后台管理 利用django-admin-bootstrap美化界面 template,view与动态URL 多说评论功能 Markd ...

  4. class id 区别

    [1].id是唯一的,一个元素只能有一个,不能重复class可以重复 <div> <img src="" width="100%"/> ...

  5. 【bzoj1019】汉诺塔

    [bzoj1019]汉诺塔 题意 传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1019 分析 思路1:待定系数+解方程 设\(f[n]\)为 ...

  6. Android Studio2.0 教程从入门到精通Windows版 - 安装篇

    详见:http://www.open-open.com/lib/view/open1468118887690.html

  7. spring core源码解读之ASM4用户手册翻译之一asm简介

    第一章:ASM介绍 1.1 ASM动机: 程序的分析,生成,转换技术可以应用到许多场景: 1.程序分析,从简单的语法解析到完整的语义分析,可以应用在程序中找到潜在的bug,发现无用的代码,工程代码的逆 ...

  8. uva 10245 近期点对问题

    分治法的典例 当练手了 奇妙的是.使用inplace_merge按说应该是O(n)的算法.可是用sort nlogn的算法反而更快 先上快排版 #include <cstdio> #inc ...

  9. ORACLE中如何查找定位表最后DML操作的时间小结

    在Oracle数据库中,如何查找,定位一张表最后一次的DML操作的时间呢? 方式有三种,不过都有一些局限性,下面简单的解析.总结一下. 1:使用ORA_ROWSCN伪列获取表最后的DML时间 ORA_ ...

  10. Node.js机制及原理理解初步【转】

    一.node.js优缺点 node.js是单线程. 好处就是 1)简单 2)高性能,避免了频繁的线程切换开销 3)占用资源小,因为是单线程,在大负荷情况下,对内存占用仍然很低 3)线程安全,没有加锁. ...