SCJSONUtil

轻量、方便的 JSON 和 Model 互转框架,支持 iOS/macOS 平台

View on GitHub

SCJSONUtil

CI Status Version License Platform

特性

  1. 小巧,方便,功能强大
  2. 支持自定义属性名(比如服务器返回的是id,我们的model里可定义为uid)
  3. 支持类型自动匹配(比如服务器返回的是Number,model里定义的是String,那么会解析为 String)

在 2.1 之前该框架会将服务器返回的字段统统转为 NSString 类型,因此 model 的头文件里定义的全都是 NSString 类型,这对于使用者来说是个恶心的限制,有用户还有我的团队都给我反馈过这个问题,因此我决定支持下类型自动匹配的功能,因此更加完美了呢!

使用 CocoaPods 安装

Podfile 文件里添加:

target 'TargetName' do
    pod 'SCJSONUtil'
end

使用说明

《一看二建三解析》,直接看代码比较直观:

{
    "code": "0",
    "content": {
        "gallery": [
                    {
                    "isFlagship": "0",
                    "name": "白色情人节 与浪漫牵手",
                    "pic": "http://pic16.shangpin.com/e/s/15/03/06/20150306174649601525-10-10.jpg",
                    "refContent": "http://m.shangpin.com/meet/189",
                    "type": "5"
                    },
                    ...
                    ]
      }
}
@interface GalleryModel : NSObject

@property (nonatomic, copy) NSString *isFlagship;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *pic;
@property (nonatomic, copy) NSString *refContent;
@property (nonatomic, copy) NSString *type;

@end
假设responseJSON是服务器返回的json数据,那么正规的写法是先判断 code 是否等于 0,然后再取出 gallery 对应的json,然后交给 JSONUtil !JSONUtil提供了便捷的方法能够方便将它取出来:

//1.根据 keypath 取出目标json
    id findedJSON = SCFindJSONwithKeyPath(@"content/gallery", responseJSON); 
//2.使用 JSONUtil 解析
    NSArray *models = SCJSON2Model(findedJSON, @"GalleryModel");

//models 就是你想要的GalleryModel数组了!

其他的用法,可以参考demo。


核心思想

  1. 递归,JSON 是可以嵌套的,因此这是一个递归的问题;
  2. 遍历 JSON,而不是遍历model
  3. 适当的地方进行 ValueTransfer,做到类型自动匹配
  4. 通过 kvc 给 model 赋值

核心的思想应该是一样的,不过具体实现差别还真的挺大的!

主流 JSON 转 Model 流程

这里要解释下第二点,因为这里我和其他的 JSON 转 Model 框架的实现大不相同!先来看下其他的主流思想:

JSONUtil 转 Model 流程

JSONUtil 与主流转换框架的区别

可以看出: JSONUtil 遍历的是服务器返回的 JSON 而不是model的全部属性,并且没做 cache !这是与其他框架有很大区别!

JSONUtil 不做 cache 的原因

知道了主流做法后,再来看下 JSONUtil 是如何处理的吧,你会发现 JSONUtil 有很有特色,因为随大流地的去模仿做 cache ,遍历 model 的全部属性,之所以没有这么做,是因为我觉得 没有必要

这是我的做的测试:

    NSDictionary *userInfoDic = [self readUserInfo];

    [self testCount:100000 work:^{
        UserInfoModel *uModel = [UserInfoModel instanceFormDic:userInfoDic];
    }];
    // 10000 次转换耗时:0.51412s
    // 100000 次转换耗时:4.61152s

也就是说使用 JSONUtil 转换一个嵌套4层(里面也有数组)的 model ,转换一次需要: 0.0514ms.

为什么 JSONUtil 选择遍历服务器返回的 JSON ?

遍历终究是要做的,有两种做法,一种是遍历 model的所有属性,另一种是遍历 服务器返回的json;究竟如何选择,困扰了我许久,最后我选择了后者,因为前者的代价较高,需要层层向上遍历,最可恶的是递归的出口不好把握,因此选择了后者规避了这个问题!

另一方面选择后者是因为,根据我解析的习惯是,服务器定义的字段我都会解析,但是有的字段服务器可能不返回,如果按照前者的遍历方式,会增加几次多余的遍历;当然我否定使用后者不会出现多余的遍历,这个定义model的习惯和服务器返回json的空值都有关系!

版本