我眼中的开源库源码之JSONModel(一)

JSONModel 一个解析 JSON 数据的开源库,可以将 JSON 数据直接解析成自定义的 model ,其中对数据类型的检查和对数据类型的转换比较贴心。最近在项目中使用了以后觉得确实方便很多,推荐给大家。(PS:由于实现的原理在swift中并不支持,所以swift代码了解就可以)。

国际惯例介绍下背景,曾经有一段时间一直要写接口,自然少不了解析获得的 JSON 数据,觉得真的是一种非常机械重复的过程,懵懵懂懂的写一个基于 runtime 的解析器,感觉用起来方便了不少,但是在错误处理和一些特殊情况下使用起来还是觉得有一些不灵活。多年以后偶然的机会又遇到了相同的工作,解析 JSON 数据,这次选择了相对讨巧的办法,使用成熟的开源库来解决。想起那句话“知其然,知其所以然”,决定深入的分析下,把我的理解也分享给大家。

先从使用说起吧,使用 JSONModel 非常简单,只需要将你的 model 类继承自 JSONModel ,而同时 model 中的属性名又恰巧可以和 JSON 数据中的 key 名字一样的话,那么非常恭喜你,你的工作已经完成90%。如果你还有特殊需求实际上写起来也非常方便,我觉得完全可以覆盖日常90%的工作。其他的功能我们会在分析源码的时候看到。

JSONModel 不只使用非常方便而且还会帮你检查 JSON 数据的完整性,如果 JSON 数据不完整的话是要返回 nil 的。它还提供了基本的数据类型转换,比如服务器错将数字传成字符串的话 JSONModel 也会帮你转换成你期望的类型。好啦,广告做到这里,请相关部门去收一下广告费。

先看一下文件结构,无视掉网络相关的类是这样的

既然我们是继承自JSONModel,那我们就看看JSONModel

头文件分成三部分: 1) Property protocol 2) AbstractJSONModelProtocol 3) JSONModel

第一部分 Property protocol

@protocol Ignore

@end

我们看到的只是4个空的协议 Ignore,Optional,Index,ConvertOnDemand,分别对应的四种使用方法,忽略、可选、排序、延迟加载,粗看起来貌似都是空的协议没有什么实际的使用价值,但是我觉得正是作者代码精彩之处,我们都知道在 runtime 系统中,每一个对象实例都有一个isa指针(PS:新的 runtime 命名可能有些变化,但是原理相通)指向的是该实例变量的 Class 对象,进而得到该实例对象的所有信息。而 JSONModel 正是利用 runtime 系统的这个特性进行解析数据的,在Class对象中我们可以获得属性的相关描述也包括了其符合的协议,这样这四个空协议就起到了画龙点睛的作用,灵活度直线提高。比如在解析JSON的时候我们发现其某些属性符合Igonre就不会解析该属性,其他的协议同理。美中不足由于swift中对这种机制支持的并不友好所以JSONModel应该不太适用。

还有最后一点作者非常贴心的实现两个Category为了防止编译器的警告,大家也可以参考一下这种写法。

第二部分 AbstractJSONModelProtocol

是 JSONModel 符合的抽象协议。如果你的类也符合该协议, 可以理解于是和JSONModel一样的,可以将不继承自 JSONModel 的类当作属性一起解析,一般还是推荐继承自 JSONModel 不然里面很多细节都要你自己去实现。

第三部分 JSONModel

-(instancetype)initWithString:(NSString*)string error:(JSONModelError**)err;

-(instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError**)err;

-(instancetype)initWithDictionary:(NSDictionary*)dict error:(NSError **)err;

-(instancetype)initWithData:(NSData *)data error:(NSError **)error;

四个初始化方法,实际上最后都是使用initWithDictionary来实现的。具体实现可以参考代码

顺便提一下instancetype这个类型是苹果为了解决我们在继承的时候,返回类型的问题,如果你没有没有遇到或者不了解可以注意下。这样写避免了一直被诟病的反悔 id 类型,感兴趣可以自己查一下相关的资料。

还有一些方便的方法暂时不提,还有几个可以重载的方法.

+(JSONKeyMapper*)keyMapper;

keyMapper  这个是解决JSON中的key和属性名字对应不上时使用的。只对该类生效

setGlobalKeyMapper 这个mapper和keyMapper作用一样只是对所有的JSONModel的子类都生效的一个对应关系

propertyIsOptional 和propertyIsIgnored 是协议的方法版,设想你有1000个属性要写明这两个协议你会不会疯掉。也许直接返回一个YES或者NO就能解决问题对吧。

欢迎来二一个灌水

未完待续

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 我们接着上回的思路看,上面第一行就是一个条件编译。 #if !__has_feature(objc_arc)#er...
    lxyeslxlx11阅读 805评论 0 1
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,198评论 4 61
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,860评论 18 139
  • 儿子,你的十二年寒窗终于走到尽头了,明天,你将会和近干万的高三学子一起走向人生第一个重大的战场。而此时,竟然有诸多...
    沙漠里的夕阳阅读 208评论 0 1
  • 有一段时间喜欢在图书馆里闲逛,各个书架间穿梭,专门找那种薄薄册、名字有趣的书来读。一次,偶然翻到了柳美里的《私...
    陈十五阅读 1,157评论 5 9