zoukankan      html  css  js  c++  java
  • [原创]一种自动地将继承自NSObject的自定义类序列化成JSON的方法

      最近因为项目需求,需要将一些自定义的类序列化为JSON,网上有很多好用的第三方序列化工具,但都只能序列化一些基本类型,如NSNumber,NSString与NSDictionary这种,没有一种第三方工具提供直接将自定义类序列化的方法(至少据我所知:),而对于这种序列化自定义的类的需求,网上能查到的方法只有将自定义的类手动的转存为一个NSDictionary,然后再使用第三方工具来序列化。例如对于一个类Foo,有如下定义:

     1 @interface Foo : NSObject
     2 
     3 {
     4 
     5   NSString *_property1;
     6 
     7   NSString *_property2;
     8 
     9 }
    10 
    11 @property(nonatomic,retain)NSString *property1;
    12 
    13 @property(nonatomic,retain)NSString *property2;
    14 
    15  
    16 
    17 @implementation Foo
    18 
    19 @synthesize property1 = _property1;
    20 @synthesize property2 = _property2;
    21 
    22 - (id)init
    23 {
    24     self = [super init];
    25     
    26     if (self)
    27     { 
    28         _property1 = @"haha";
    29         _property2 = @"hehe"; 
    30     }
    31 
    32     return self;
    33 }
    34 
    35 - (void)dealloc
    36 
    37 {
    38 
    39   [super dealloc];
    40 
    41 }

    要序列化它的方法只有:

     1 Foo *foo = [[Foo alloc] init];
     2 
     3 NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
     4 
     5                           foo.property1,@"property1",
     6 
     7                              foo.property2,@"property2",               
     8 
     9                                 nil];
    10 
    11 [[JSONSerializer serializer] serializer:dict];

    这种方法的缺陷在于太不灵活,每一次序列化的时候都需要写很多重复的代码。因为在JAVA中有工具通过反射机制可以实现自动的序列化自定义类,于是抱着试一试的心态,开始寻找Objective-C中对应的方法。功夫不负苦心人,一位stackoverflow上的仁兄的回复提醒了我,iOS中的有Runtime Programming这样一种技术,通过阅读相应的文档,最终我找到了解决的方法。

    iOS的Runtime Programming中提供了一系列强大的方法在运行时对类进行操作,比如获取类的属性信息,类的协议信息,甚至是修改,增加,删除类的方法。对于我的需求而言,能够获取类的所有属性信息已经足够了。实际上我们需要解决的问题,就是动态的获取一个类中所有的属性名,只要能够获取这个,再通过这些属性名找到对应的属性值,最终把这些名-值建立成对,放入一个NSDictionary中,就可以完成序列化的工作了。

    想到这里,可以说要做什么已经清楚了,接下来就是实干!我用苹果的官方文档给的例子,写了一个获取一个类所有属性名的方法:

     1     Foo *foo = [[Foo alloc] init];
     2     
     3     id fooClass = objc_getClass("Foo");
     4     
     5     unsigned int outCount, i;
     6     
     7     objc_property_t *properties = class_copyPropertyList(fooClass, &outCount);  //获取该类的所有属性
     8     
     9     for (i = 0; i < outCount; i++)
    10 
    11   {
    12         
    13         objc_property_t property = properties[i];
    14        
    15 
    16     //property_getName()返回属性的名字 在Foo中分别是 property1和property2
    17 
    18     //property_getAttributes()返回属性的属性,如是retain还是copy之类的
    19        
    20 
    21     //这个方法输出了该类所有的属性名与对应的属性的属性(好绕口啊)
    22 
    23     NSLog(@"%s %s\n", property_getName(property), property_getAttributes(property));  
    24         
    25     }

      我们知道,对于一个定义了@property的NSObject来说,只要调用与属性名相同名字的方法,便可以得到这个属性的值,如:[foo property1];会返回 @"haha" ,为了获取对应属性的值,我们只要把属性的名字用NSSelectorFromString()方法转换成selector,然后让这个类foo来调用就可以了。

      至此,可以说所有的难点都解决了,接下来就是把这个些东西组合起来,来生成NSDictionary了。下面的很简单,我就不写了:)

      第一次写这么长的技术文章,可能写的有点糙,如果有相关问题,欢迎留言询问。

      补充一点,要使用Runtime Programming的方法,需要引用头文件:

    1 #import <Foundation/NSObjCRuntime.h>
    2 #import <objc/runtime.h>

      还有一点,这个方法我不确定能否通过苹果的审核,不过既然苹果的文档让用,我觉得应该没什么问题。

      转载请注明出处.



  • 相关阅读:
    vi删除前n个字符
    ubuntu自定义登录session和桌面环境
    linux出错处理
    获取用户id
    c关键字控制语句运算符小结
    红帽Linux启动流程详解
    C语言中的文本流与二进制流的区别
    c简单排序字符串
    linux挂载磁盘优盘
    strcpy之段错误
  • 原文地址:https://www.cnblogs.com/flyFreeZn/p/2285376.html
Copyright © 2011-2022 走看看