JSON

实现一个JSON映射库

字号+ 作者:H5之家 来源:H5之家 2017-04-16 13:04 我要评论( )

JSON序列化框架是iOS开发的必备代码库,我这里指的序列化是指JSON-Models之间的转换。目前比较流行的有Mantle,JSONModel,还有国产的MJExtension,YYModel等。

> 软件编程 > IOS开发 >

实现一个JSON映射库 2017-04-10 12:42 出处:清屏网 人气: 

JSON序列化框架是iOS开发的必备代码库,我这里指的序列化是指JSON<->Models之间的转换。目前比较流行的有Mantle,JSONModel,还有国产的MJExtension,YYModel等。这些库都很优秀可以满足日常大部分的需求。 为什么要重复造轮子

我在项目中用过Mantle和JSONModel,用起来感觉都挺好的,但是它们都有一些方面我感觉不是很喜欢。

  • Mantle和JSONModel都需要继承自它们的基类来实现相关的能力。这增加了库与业务代码的耦合。比方说,我想在项目里面同时使用不同的Model类型就难以实现了。
  • 对于自定义类型NSArray,JSONModel需要自定一个和类型同名的protocol来实现类型转换。例如:
  • @protocol CustomClass<NSObject> @end @interface CustomClass : NSObject @end //我总觉得这种方式有点hack,为什么一定要写一个多余的protocol呢? @interface AModel : JSONModel @property (nonatomic,strong) NSArray<CustomClass> *customs; @end
  • Mantle自定义类型则需要自己实现对应的ValueTransformer。
  • 另外在JSONModel的使用当中我还遇到过一个诡异的问题,比如时候你的Model实现了一下自定义的protocol的时候会导致序列化失败,我看了一下代码应该是oc类型解析的是时候出了问题。
  • 在Mantle和JSONModel之间选一个话,我会选择Mantle。Mantle非常稳定,功能强大,而且设计更加合理,功能强大。但是源代码而言我比较喜欢JSONModel的风格,思路清晰,风格统一。Mantle不知道是设计比较复杂还是怎样,代码看起来没有那么整洁清晰,当然这只是个人的一些看法。虽然说一些测评文章指出Mantle的性能在几个流行的框架中算是垫底的,但实际来看,稳定性和好的设计才是我们开发重点关注的点。

    实际上Mantle已经够用了,对于我自己来说它可能太重了。我的理解中JSON序列化的框架的职责是将JSON数据转化成Model。这其实是一个很自然的过程,我自己的需求只是需要最简单的方法转化成NSObject就行了,我不需要在框架内进行类似于NSDate这种复杂的转换。所以我打算实现一个最简易映射框架,同时也作为一个学习过程。

    基本思路

    大部分JSON映射框架都是基于Cocoa强大的runtime能力实现的。我们可以动态的获取类的properties,然后使用强大KVC来实现动态赋值。

    我的思路非常简单直接:

    1.获取类所有的Properties,然后解析出每个property的必要信息(类型,keypath等等)。

    2.使用JSONSerialization将Data或者String转换成NSDictionary或者NSArray,枚举类的properties通过key来获取NSDictionary里面的value然后赋值到对象里面。

    获取Class的properties

    利用oc的runtime方法,我们可以用一个循环拿到这个类的所有properties。为此我增加了一个NSObject的category:

    + (NSArray<JDCClassProperty *> *)jdc_classProperties { //这里我们缓存一下properties一定程度上提升效率。 NSArray *properties = [self getCacheProperties]; if (!properties) { Class cls = self; NSMutableArray *all = [NSMutableArray new]; //我们需要遍历整一个继承链来获取所有的properties while(cls != [NSObject class]){ [all addObjectsFromArray:[self jdc_getProperties:cls]]; cls = [cls superclass]; } properties = all; [self setCachedProperties:all]; } return properties; } + (NSArray *)jdc_getProperties:(Class)class { unsigned int pCount = 0; //使用runtime相关方法来获取properties。 objc_property_t *properties = class_copyPropertyList(class, &pCount); NSMutableArray *pArray = [NSMutableArray new]; for(int i = 0 ; i < pCount ; i++){ objc_property_t property = properties[i]; //我在JDCClassProperty初始化阶段对property 进行解析 JDCClassProperty *clsProperty = [[JDCClassProperty alloc] initWithProperty:property]; if (!clsProperty.isReadyOnly) { [pArray addObject:clsProperty]; } } return pArray; } + (NSArray *)getCacheProperties { return objc_getAssociatedObject(self, &kAssociatedCachePropertiesKey); } + (void)setCachedProperties:(NSArray *)properties { objc_setAssociatedObject(self, &kAssociatedCachePropertiesKey,properties, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } 解析Property

    拿到的原始property是一种Type Encoding的字符串形。Apple有文档解释Type Encoding 。我们需要对其进行解析,一个典型的NSString Encoding为这种形式:

    T@"NSString",&,N,V_login

    这个字符串包含了property的类型,读写属性,以及key(name)。把这些信息解析出来即可。我们看一下形式大概就知道Encoding的格式,具体可以去阅读以下文档。解析代码:

    - (void)_inspectProperty:(objc_property_t)property { NSString *str = [self getPropertyAttributeString:property]; NSArray *components = [str componentsSeparatedByString:@","]; NSString *token = components[0]; //R代表只读属性,这里我们忽略只读属性 _isReadyOnly = [components containsObject:@"R"]; //'@'代表的是对象,是我们重点关注的类型。 if ([token characterAtIndex:1] == '@' && token.length > 3 && [token characterAtIndex:2] == '\"') { NSString *name = [token substringWithRange:NSMakeRange(3, token.length-4)]; _propertyTypeName = name; //JSONSerialization所支持的标准JSon类型。 if (sAllowedJSONTypes[name]) { _propertyType = JDCClassPropertyStandandJsonType; _isArray = [name isEqual:@"NSArray"]; }else{ //自定义类型,我们需要重点处理的类型。 _propertyType = JDCClassPropertyCustomType; } }else{ NSString *encodeStr = [token substringWithRange:NSMakeRange(1, 1)]; NSNumber *type = sTypeMappings[encodeStr]; if (type) { _propertyType = [type unsignedIntegerValue]; }else{ _propertyType = JDCClassPropertyOtherType; } } }

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • JSON教程免费下载

      JSON教程免费下载

      2017-04-16 14:00

    • Json for Java API学习

      Json for Java API学习

      2017-04-16 13:03

    • ajax技术,json,xml,post

      ajax技术,json,xml,post

      2017-04-16 08:06

    • Google Gson的使用方法及JSON 技术对比

      Google Gson的使用方法及JSON 技术对比

      2017-04-16 08:05

    网友点评