一种自动的将自定义类序列化为JSON的方法
2012-04-02 06:41
337 查看
最近因为项目需求,需要将一些自定义的类序列化为JSON,网上有很多好用的第三方序列化工具,但都只能自动序列化一些基本类型,如NSNumber,NSString与NSDictionary这种,没有一种第三方工具提供直接将自定义类序列化的方法(至少据我所知:),而对于这种序列化自定义的类的需求,网上能查到的方法只有将自定义的类手动的转存为一个NSDictionary,然后再使用第三方工具来序列化。例如对于一个类Foo,有如下定义:
?
要序列化它的方法只有:
?
这种方法的缺陷在于太不灵活,每一次序列化的时候都需要写很多重复的代码,上面的代码还没有考虑属性值为nil的情况(因为当属性值为nil时,NSDictionary会认为初始化结束)。因为在JAVA中有工具通过反射机制可以实现自动的序列化自定义类,于是抱着试一试的心态,开始寻找Objective-C中对应的方法。功夫不负苦心人,一位stackoverflow上的仁兄的回复提醒了我,iOS中的有RuntimeProgramming这样一种技术,通过阅读相应的文档,最终我找到了解决的方法。
iOS的RuntimeProgramming中提供了一系列强大的方法在运行时对类进行操作,比如获取类的属性信息,类的协议信息,甚至是修改,增加,删除类的方法。对于我的需求而言,能够获取类的所有属性信息已经足够了。实际上我们需要解决的问题,就是动态的获取一个类中所有的属性名,只要能够获取这个,再通过这些属性名找到对应的属性值,最终把这些名-值建立成对,放入一个NSDictionary中,就可以使用第三方工具完成序列化的工作了。
想到这里,可以说要做什么已经清楚了,接下来就是实干!我用苹果的官方文档给的例子,写了一个获取一个类所有属性名的方法:
?
我们知道,对于一个定义了@property的NSObject来说,只要调用与属性名相同名字的方法,便可以得到这个属性的值,如:[fooproperty1];会返回@"haha",为了获取对应属性的值,我们只要把属性的名字用NSSelectorFromString()方法转换成selector,然后让这个类foo来调用就可以了。
至此,可以说所有的难点都解决了,接下来就是把这个些东西组合起来,来生成NSDictionary了。下面的很简单,我就不写了:)
最终序列化的代码如下:
?
这里主要是提供一种思路,可能这种解决方法还会有些欠缺的地方,希望可以和大家一起讨论下。内容可能写的有点糙,如果有相关问题,欢迎留言询问。
补充一点,这个方法我不确定能否通过苹果的审核,不过既然苹果的文档让用,我觉得应该没什么问题。
之前排版有点问题,现在好了:)
1234567891011121314151617181920212223242526272829303132333435363738394041 | @interface Foo: NSObject { NSString *_property1; NSString *_property2; } @property ( nonatomic ,retain) NSString *property1; @property ( nonatomic ,retain) NSString *property2; @implementation Foo @synthesize property1=_property1; @synthesize property2=_property2; -( id )init { self =[ super init]; if ( self ) { _property1=@ "haha" ; _property2=@ "hehe" ; } return self ; } -( void )dealloc { [ super dealloc]; } |
1234567891011 | Foo*foo=[[Fooalloc]init]; NSDictionary *dict=[ NSDictionary dictionaryWithObjectsAndKeys: foo.property1,@ "property1" , foo.property2,@ "property2" , nil ]; [[JSONSerializerserializer]serializer:dict]; |
iOS的RuntimeProgramming中提供了一系列强大的方法在运行时对类进行操作,比如获取类的属性信息,类的协议信息,甚至是修改,增加,删除类的方法。对于我的需求而言,能够获取类的所有属性信息已经足够了。实际上我们需要解决的问题,就是动态的获取一个类中所有的属性名,只要能够获取这个,再通过这些属性名找到对应的属性值,最终把这些名-值建立成对,放入一个NSDictionary中,就可以使用第三方工具完成序列化的工作了。
想到这里,可以说要做什么已经清楚了,接下来就是实干!我用苹果的官方文档给的例子,写了一个获取一个类所有属性名的方法:
12345678910111213141516171819202122232425 | Foo*foo=[[Fooalloc]init]; id fooClass=objc_getClass( "Foo" ); unsigned int outCount,i; objc_property_t*properties=class_copyPropertyList(fooClass,&outCount); //获取该类的所有属性 for (i=0;i<outCount;i++) { objc_property_tproperty=properties; //property_getName()返回属性的名字在Foo中分别是property1和property2 //property_getAttributes()返回属性的属性,如是retain还是copy之类的 //这个方法输出了该类所有的属性名与对应的属性的属性(好绕口啊) NSLog (@ "%s%s\n" ,property_getName(property),property_getAttributes(property)); } |
至此,可以说所有的难点都解决了,接下来就是把这个些东西组合起来,来生成NSDictionary了。下面的很简单,我就不写了:)
最终序列化的代码如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 | NSString *className= NSStringFromClass ([theObject class ]); const char *cClassName=[classNameUTF8String]; id theClass=objc_getClass(cClassName); unsigned int outCount,i; objc_property_t*properties=class_copyPropertyList(theClass,&outCount); NSMutableArray *propertyNames=[[ NSMutableArray alloc]initWithCapacity:1]; for (i=0;i<outCount;i++){ objc_property_tproperty=properties; NSString *propertyNameString=[[ NSString alloc]initWithCString:property_getName(property)encoding: NSUTF8StringEncoding ]; [propertyNamesaddObject:propertyNameString]; [propertyNameStringrelease]; NSLog (@ "%s%s\n" ,property_getName(property),property_getAttributes(property)); } NSMutableDictionary *finalDict=[[ NSMutableDictionary alloc]initWithCapacity:1]; for ( NSString *keyinpropertyNames) { SEL selector = NSSelectorFromString (key); id value=[theObjectperformSelector: selector ]; if (value== nil ) { value=[ NSNull null]; } [finalDictsetObject:valueforKey:key]; } [propertyNamesrelease]; NSString *retString=[[CJSONSerializerserializer]serializeDictionary:finalDict]; [finalDictrelease]; return retString; |
补充一点,这个方法我不确定能否通过苹果的审核,不过既然苹果的文档让用,我觉得应该没什么问题。
之前排版有点问题,现在好了:)
相关文章推荐
- 一种自动的将自定义类序列化为JSON的方法
- 一种自动的将自定义类序列化为JSON的方法
- 一种自动的将自定义类序列化为JSON的方法
- 一种自动的将自定义类序列化为JSON的方法
- [原创]一种自动地将继承自NSObject的自定义类序列化成JSON的方法
- 一种自动的将自定义类序列化为JSON的方法
- 一种基于自定义代码的asp.net网站首页根据IP自动跳转指定页面的方法!
- python Json的一点收获,自定义序列化方法
- 一种基于自定义代码的asp.net网站首页根据IP自动跳转指定页面的方法!
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
- python Json的一点收获,自定义序列化方法
- python Json的一点收获,自定义序列化方法
- c# Json 自定义类作为字典键时,序列化和反序列化的处理方法
- 一种基于自定义代码的asp.net网站首页根据IP自动跳转指定页面的方法!
- 一个自定义的json序列化对象的方法
- 工具方法,可以将指定的表单中的输入项目序列化为json数据
- 封装JSON数据转自定义HTML方法parseHTML
- 一种基于自定义代码的asp.net网站访问IP过滤方法!
- django中两张表有外键关系的相互查找方法,自定义json编码方法