Swift:分别使⽤SwiftyJSON、ObjectMapper、HandyJSON处理
JSON
2018.12.21 00:43:33字数 1,947阅读 2,612
处理JSON数据是在开发过程中⼀定会遇到的⼀项操作,通常情况下我们会先把JSON转为Dictionary,记住每个数据对应的Key,然后根据这个Key在Dictionary中取出对应的Value值来,那么除了在遇到⼀些⽐较复杂的JSON数据时候会显得有些头疼和繁琐之外,可能还会经常出现以下各种错误:
因此,为了解决这些问题,很多处理JSON的开源库应运⽽⽣。在Swift中,这些开源库主要朝着两个⽅向努⼒:
1. 保持JSON语义,直接解析JSON,但通过封装使调⽤⽅式更优雅、更安全;
2. 预定义Model类,将JSON反序列化为类实例,再使⽤这些实例;
针对以上两个⽅向,⽐较出名的有SwiftyJSON、ObjectMapper、HandyJSON,下⾯就根据我个⼈的开发经验来分享⼀下各个框架在处理JSON过程中的使⽤。
1、SwiftyJSON
SwiftyJSON的使⽤相对来说是最⼴的,它是针对上⾯提到的两个⽅向中的第⼀条产⽣的⼀个库,本质上仍然是根据JSON结构去取值,使⽤起来⽐较顺⼿、清晰。
通常我们拿到数据会进⾏⾮常⿇烦的Optinonal(可选类型)进⾏拆包(Wrapping )操作,SwiftyJSON内部会⾃动对Optinonal进⾏拆包,⼤⼤简化了代码,解析⾮常⽅便,拿到的Json数据data直接扔进去,例如:
我们不需要考虑服务器返回的是什么类型,⽐如去请求⼀个学⽣的age,我们想要获得Int类型或者String类型都可以
通过 .stringValue、 .intValue 就可以获得不可选值类型,如果没有获取到数据的话就会返回⼀个默认值即 .stringValue获得空字符串"",.intValue得到 0,.arrayValue获得空数组[],我们就不⽤判断拆包了。除某些特定需要判断类型的场景除外。
如果我们拥有的是⼀个JSO格式的字符串,那么:
实际开发中,我们仅仅是对返回的数据进⾏JSON读取是不够的,如果遇到许多地⽅都⽤到了 name 值,但是当服务器给我们返回的字段名字改了,我们改项⽬时就会显得⿇烦,甚⾄造成修改不完全,所以我们对数据封装⼀下转为模型,这样修改时只⽤修改model的⼀个属性就可以了 ,  例如:js获取json的key和value
创建模型,使⽤Class也可以,但是如果不需要继承或者不是很复杂,推荐使⽤结构体struct (可以参考)
下⾯是如何将JSON转成模型Model
复杂模型,例如:
这时候我们就要创建嵌套模型:
这样就能很⽅便的取出 scores ⾥⾯的值
以上就是针对SwiftyJSON 的⼀些JSON处理
2 、ObjectMapper
ObjectMapper不同于SwiftyJSON的是把JSON映射成对象,为了⽀持映射,ObjectMapper中定义了⼀个协议,类 class 或者结构体 struct 需要实现Mappable协议,这个协议包含下⾯两个⽅法:
ObjectMapper使⽤⾃定义的 <- 运算符来声明成员变量和JSON的映射关系,例如:
对象实现了 Mappable、ObjectMapper 就可以轻松的实现JSON 之间的转换
或者:
或者复杂的数据结构:
3、HandyJSON
在使⽤了SwiftyJSON和ObjectMapper后会发现,这两种⽅法都还是有些缺陷的,⾸先我们要在model中指明每个属性对应的字段名,不仅代码侵⼊量⼤,⽽且拼写错误,后期维护困难,⽽且Mapping函数要求开发者⾃定义
HandyJSON 采⽤Swift反射+内存赋值的⽅式来构造Model实例,规避了上述两个⽅案遇到的问题,不过HandyJSON也并⾮完美⽆缺,如经常造成的内存泄露,兼容性差等问题,所以建议使⽤最新的HandyJSON库
Model类想⽀持通过HandyJSON来反序列化,只需要在定义时,实现HandyJSON协议,这个协议只要求实现⼀个空的init()函数
下⾯就是⼀个举例:
假如我们拿到这样的⼀个JSON数据,要怎样来做反序列化呢
这样只需调⽤它的反序列函数就可以了,我们不⽤再⼀⼀指明model属性对应的字段名称,也不⽤担⼼定义错了数据类型。这是⼀个⽐较简单的JSON转model,我们经常会遇到些复杂的JSON数据
开发当中我们还会遇到些嵌套类型的model,如果model中的某⼀个属性是另外⼀个⾃定义model,那么只要那个model类也实现了HandyJSON协议,就⼀样可以转换:
有时候服务端返回给我们很多和model⽆关信息,如 statusCode  , debugMessage等,或者有⽤的数据是在某个节点以下,那么我们可以指定反序列化哪个节点:
如果某个model类继承⾃另⼀个model类,那么只需要这个⽗model类实现 HandyJSON 协议就可以
此时我们要注意不能再使⽤struct,⽽要使⽤class创建model
HandyJSON还提供了⼀个扩展能⼒,允许⾃⾏定义model类某个字段的解析Key、解析⽅式。
某个Model中,我们不想使⽤和服务端约定的Key作为属性名,想⾃⼰定⼀个
有些类型如enum、tuple是⽆法直接从JSON中解析出来的,但我们在Model类中有这样的属性
HandyJSON协议提供了⼀个可选的mapping()函数,我们可以在其中指定某个字段⽤什么Key、或者⽤什么⽅法从JSON中解析出它的值。如我们有⼀个model类和⼀个服务端返回的JSON数据:
我们可以看到,User 的 id 属性和 json 的Key是对应不上的,⽽对于grandpas这个属性来说,它是⼀个数组,做不到从json中的 "哈哈, 嘻嘻" 解析出来。所以我们要定义⼀个Mapping函数来做这两个⽀持:
这样就实现了HandyJSON的⾃定义解析⽅式
HandyJSON还⽀持枚举属性,实现⽀持枚举,enum 需要实现 HandyJSONEnum 协议
使⽤这些库前要先分别导⼊SwiftyJSON,ObjectMapper, HandyJSON 如果需要导⼊的⽂件很多,那么我们可以挑选⼀个⾃⼰喜欢的⽂
件 @_exported import SwiftyJSON, @_exported import ObjectMapper,@_exported import HandyJSON ,如此只需要导⼊⼀次就可以了
关于JSON转Model的⽅法就说这么多了,如有什么错误希望⼤家可以指出,有更多的⽅法也可以补充。谢谢!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。