1. 使用
实现的结果就是可以把任何对象转化成字典或者字典对应的JSON。字典的数据就是来自对象的属性名称和属性值 。而且是多层的,也就是说如果对象的某个属性值是另一个对象,数组,或者字典,该值都会被转换成另一个字典。
这个类型名称是PrintObject,它的所有方法都是静态的:
1234567891011 | @interface //通过对象返回一个NSDictionary,键是属性名称,值是属性值。 + //将getObjectData方法返回的NSDictionary转化成JSON + //直接通过NSLog输出getObjectData方法返回的NSDictionary + @end |
举个例子,比如用来保存数据的类型是MyData, 这个类型如下定义:
123456789 | @interface @property @property @property @property @property @property @property @end |
然后通过MyData类型创建一个复杂的对象,其中包含非对象属性,对象属性,还有包含对象的数组和字典。代码如下:
1234567891011 | MyData main.name "mgen" ; main.age MyData childOfChild.name "child of child" ; childOfChild.age MyData child.name "child" ; child.arrProp "test" , @234, @[@123, @ "array in array" , childOfChild]]; main.objProp main.dicProp "中文Key" : @3.444444, @ "object" : childOfChild}; |
OK,接着使用PrintObject类型输出这个MyData对象(上面的main变量)的字典:
12 | NSDictionary NSLog(@ "%@" , dic); |
输出:
1234567891011121314151617181920212223242526272829303132333435363738394041424344 | { age = 22; arrProp = "<null>" ; dicProp = { object = { age = "-443" ; arrProp = "<null>" ; dicProp = "<null>" ; male = 0; name = "child of child" ; nullString = "<null>" ; objProp = "<null>" ; }; "\U4e2d\U6587Key"
"3.444444" ; }; male = 0; name = mgen; nullString = "<null>" ; objProp = { age = 0; arrProp = ( test, 234, ( 123, "array in array" , { age = "-443" ; arrProp = "<null>" ; dicProp = "<null>" ; male = 0; name = "child of child" ; nullString = "<null>" ; objProp = "<null>" ; } ) ); dicProp = "<null>" ; male = 0; name = child; nullString = "<null>" ; objProp = "<null>" ; }; } |
也可以输出这个对象的JSON数据
123 | NSData NSString NSLog(@ "%@" , jsonText); |
结果:
1234567891011121314151617181920212223242526272829303132333435363738394041424344 | { "arrProp"
null , "name"
"mgen" , "age"
"objProp"
"arrProp"
"test" , 234, [ 123, "array in array" , { "arrProp"
null , "name"
"child of child" , "age"
"objProp"
null , "male"
"nullString"
null , "dicProp"
null } ] ], "name"
"child" , "age"
"objProp"
null , "male"
"nullString"
null , "dicProp"
null }, "male"
"nullString"
null , "dicProp"
"中文Key"
"object"
"arrProp"
null , "name"
"child of child" , "age"
"objProp"
null , "male"
"nullString"
null , "dicProp"
null } } } |
2. 实现
在实现上,属性的枚举是通过定义在<objc/runtime.h>中的class_copyPropertyList方法实现。其次,属性值的获取是通过KVC中的valueForKey方法,这个方法同时可以将非对象类型(如BOOL, int等)转换成NSNumber。
接着就是对数组,字典和对象类型值的嵌套处理,所有值就可以获取出来了。
至于JSON,如果正确获取了NSDictionary后,直接使用iOS 5后的NSJSONSerialization类型的dataWithJSONObject方法就可以返回包含JSON字符串的NSData对象了。
3. 下载和代码
源代码下载 下载页面
注意:链接是微软SkyDrive页面,下载时请用浏览器直接下载,用某些下载工具可能无法下载
源代码环境:Xcode 4.6.3
PrintObject.h
12345678910111213 | #import @interface //通过对象返回一个NSDictionary,键是属性名称,值是属性值。 + //将getObjectData方法返回的NSDictionary转化成JSON + //直接通过NSLog输出getObjectData方法返回的NSDictionary + @end |
PrintObject.m
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 | #import #import @implementation + { NSMutableDictionary *dic = [NSMutableDictionary dictionary]; unsigned int propsCount; objc_property_t *props = class_copyPropertyList([obj class], &propsCount); for (int i = 0;i < propsCount; i++) { objc_property_t prop = props[i]; NSString *propName = [NSString stringWithUTF8String:property_getName(prop)]; id value = [obj valueForKey:propName]; if (value == nil) { value = [NSNull null ]; } else { value = [self getObjectInternal:value]; } [dic setObject:value forKey:propName]; } return
} + { NSLog(@ "%@" , [self getObjectData:obj]); } + { return
} + { if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSNull class]]) { return
} if ([obj isKindOfClass:[NSArray class]]) { NSArray *objarr = obj; NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count]; for (int i = 0;i < objarr.count; i++) { [arr setObject:[self getObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i]; } return
} if ([obj isKindOfClass:[NSDictionary class]]) { NSDictionary *objdic = obj; NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]]; for (NSString *key in
{ [dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key]; } return
} return
} @end |