目录
返回目录
实现的结果就是可以把任何对象转化成字典或者字典对应的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 = [[MyData alloc] init];
main.name = @"mgen";
main.age = 22;
MyData *childOfChild = [[MyData alloc] init];
childOfChild.name = @"child of child";
childOfChild.age = -443;
MyData *child = [[MyData alloc] 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 = [PrintObject getObjectData: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 = [PrintObject getJSON:main options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonText = [[NSString alloc] initWithData:jsonData encoding: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
}
}
}
返回目录
在实现上,属性的枚举是通过定义在<objc/runtime.h>中的class_copyPropertyList方法实现。其次,属性值的获取是通过KVC中的valueForKey方法,这个方法同时可以将非对象类型(如BOOL, int等)转换成NSNumber。
接着就是对数组,字典和对象类型值的嵌套处理,所有值就可以获取出来了。
至于JSON,如果正确获取了NSDictionary后,直接使用iOS 5后的NSJSONSerialization类型的dataWithJSONObject方法就可以返回包含JSON字符串的NSData对象了。
返回目录
源代码下载
下载页面
注意:链接是微软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 = [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 dic;
}
+ (void)print:(id)obj
{
NSLog(@"%@", [self getObjectData:obj]);
}
+ (NSData*)getJSON:(id)obj options:(NSJSONWritingOptions)options error:(NSError**)error
{
return [NSJSONSerialization dataWithJSONObject:[self getObjectData:obj] options:options error:error];
}
+ (id)getObjectInternal:(id)obj
{
if([obj isKindOfClass:[NSString class]]
|| [obj isKindOfClass:[NSNumber class]]
|| [obj isKindOfClass:[NSNull class]])
{
return obj;
}
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 arr;
}
if([obj isKindOfClass:[NSDictionary class]])
{
NSDictionary *objdic = obj;
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
for(NSString *key in objdic.allKeys)
{
[dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key];
}
return dic;
}
return [self getObjectData:obj];
}
@end