http://www.th7.cn/Program/IOS/201309/150753.shtml

目录

1. 使用

2. 实现

3. 下载和代码


返回目录1. 使用

实现的结果就是可以把任何对象转化成字典或者字典对应的JSON。字典的数据就是来自对象的属性名称和属性值 。而且是多层的,也就是说如果对象的某个属性值是另一个对象,数组,或者字典,该值都会被转换成另一个字典。

这个类型名称是PrintObject,它的所有方法都是静态的:

@interface PrintObject : NSObject

//通过对象返回一个NSDictionary,键是属性名称,值是属性值。

+ (NSDictionary*)getObjectData:(id)obj;


//将getObjectData方法返回的NSDictionary转化成JSON

+ (NSData*)getJSON:(id)obj options:(NSJSONWritingOptions)options error:(NSError**)error;


//直接通过NSLog输出getObjectData方法返回的NSDictionary

+ (void)print:(id)obj;


@end


举个例子,比如用来保存数据的类型是MyData, 这个类型如下定义:

@interface MyData : NSObject


@property (nonatomic, strong) NSString *name;

@property (nonatomic, strong) NSString *nullString;

@property (nonatomic) int age;

@property (nonatomic) BOOL male;

@property (nonatomic, strong) MyData *objProp;

@property (nonatomic, strong) NSArray *arrProp;

@property (nonatomic, strong) NSDictionary *dicProp;


@end


然后通过MyData类型创建一个复杂的对象,其中包含非对象属性,对象属性,还有包含对象的数组和字典。代码如下:

MyData *main = [[MyDataalloc] init];

main.name = @"mgen";

main.age = 22;

MyData *childOfChild = [[MyDataalloc] init];

childOfChild.name = @"child of child";

childOfChild.age = -443;

MyData *child = [[MyDataalloc] init];

child.name = @"child";

child.arrProp = @[@"test", @234, @[@123, @"array in array", childOfChild]];

main.objProp = child;

main.dicProp = @{@"中文Key": @3.444444, @"object": childOfChild};


OK,接着使用PrintObject类型输出这个MyData对象(上面的main变量)的字典:

NSDictionary *dic = [PrintObjectgetObjectData:main];

NSLog(@"%@", dic);


输出:

{

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数据:

NSData *jsonData = [PrintObjectgetJSON:main options:NSJSONWritingPrettyPrintederror:nil];

NSString *jsonText = [[NSStringalloc] initWithData:jsonDataencoding:NSUTF8StringEncoding];

NSLog(@"%@", jsonText);


结果:

{

"arrProp" : null,

"name" : "mgen",

"age" : 22,

"objProp" : {

"arrProp" : [

"test",

234,

[

123,

"array in array",

{

"arrProp" : null,

"name" : "child of child",

"age" : -443,

"objProp" : null,

"male" : 0,

"nullString" : null,

"dicProp" : null

}

]

],

"name" : "child",

"age" : 0,

"objProp" : null,

"male" : 0,

"nullString" : null,

"dicProp" : null

},

"male" : 0,

"nullString" : null,

"dicProp" : {

"中文Key" : 3.444444,

"object" : {

"arrProp" : null,

"name" : "child of child",

"age" : -443,

"objProp" : null,

"male" : 0,

"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

#import <Foundation/Foundation.h>


@interface PrintObject : NSObject

//通过对象返回一个NSDictionary,键是属性名称,值是属性值。

+ (NSDictionary*)getObjectData:(id)obj;


//将getObjectData方法返回的NSDictionary转化成JSON

+ (NSData*)getJSON:(id)obj options:(NSJSONWritingOptions)options error:(NSError**)error;


//直接通过NSLog输出getObjectData方法返回的NSDictionary

+ (void)print:(id)obj;


@end


PrintObject.m

#import "PrintObject.h"

#import <objc/runtime.h>


@implementation PrintObject


+ (NSDictionary*)getObjectData:(id)obj

{

NSMutableDictionary *dic = [NSMutableDictionarydictionary];

unsignedint 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 = [NSStringstringWithUTF8String:property_getName(prop)];

id value = [obj valueForKey:propName];

if(value == nil)

{

value = [NSNullnull];

}

else

{

value = [selfgetObjectInternal:value];

}

[dic setObject:value forKey:propName];

}

return dic;

}


+ (void)print:(id)obj

{

NSLog(@"%@", [selfgetObjectData:obj]);

}



+ (NSData*)getJSON:(id)obj options:(NSJSONWritingOptions)options error:(NSError**)error

{

return [NSJSONSerializationdataWithJSONObject:[selfgetObjectData:obj]options:options error:error];

}


+ (id)getObjectInternal:(id)obj

{

if([obj isKindOfClass:[NSStringclass]]

|| [obj isKindOfClass:[NSNumberclass]]

|| [obj isKindOfClass:[NSNullclass]])

{

return obj;

}


if([obj isKindOfClass:[NSArrayclass]])

{

NSArray *objarr = obj;

NSMutableArray *arr = [NSMutableArrayarrayWithCapacity:objarr.count];

for(int i = 0;i < objarr.count; i++)

{

[arr setObject:[selfgetObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i];

}

return arr;

}


if([obj isKindOfClass:[NSDictionaryclass]])

{

NSDictionary *objdic = obj;

NSMutableDictionary *dic = [NSMutableDictionarydictionaryWithCapacity:[objdiccount]];

for(NSString *key in objdic.allKeys)

{

[dic setObject:[selfgetObjectInternal:[objdic objectForKey:key]] forKey:key];

}

return dic;

}

return [selfgetObjectData:obj];

}


@end