一、简介

对于ios开发中会经常用到json,而且网上也会有许多第三方的库,例如:SONKit、SBJson、TouchJson等。

也有许多人对以上库做过一些性能测试,发现JSONKit非常高效而且易用,对比同类型的库有非常明显的性能优势,见下图:


所以本人也使用JSONKit来处理JSON数据。

二、JSONKit用法简介

上网搜一下"JSONKit用法”会有很多资料,所以我只是简单说一下和需要注意的地方。

JSONKit使用很简单,首先要引人JSONKit.h;经常使用的方法如下:

1.转换为JSON的方法

通常都是讲NSArray和NSDictionary转换为JSON,代码如下:

- (NSString *)sampleArrayTojson
{
		//数组
	NSArray *array = [[NSArray alloc] initWithObjects:@"a",@"b",@"c",nil];
	NSString  *json = [array JSONString];
	NSLog(@"json = %@", [NSString stringWithString: json]);
	[array release];
		//json= ["a","b","c"]
	return json;
}

- (NSString *)sampleDicTojson
{
		//字典类型(对象)
	NSArray *array1 = [NSArray arrayWithObjects:@"任何",@"中国",nil];
	NSArray *array2 = [NSArray arrayWithObjects:[NSNumber numberWithBool:YES],[NSNumber numberWithInt:30],nil];
	NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:array1,@"x",array2,@"y",nil];
	NSString *json = [dic JSONString];
	NSLog(@"json = %@", [NSString stringWithString: json]);
	return json;
}




2.JSON转换为NSArray和NSDictionary

- (NSArray *)sampleJsonToArray
{
	JSONDecoder *jd=[[JSONDecoder alloc] init];

	NSString *json = [self sampleArrayTojson];
	
	NSArray *array = [jd objectWithUTF8String:(const unsigned char *)[json UTF8String] length: (unsigned int)strlen([json UTF8String])];
	
	for (NSString *string in array)
	{
		NSLog(@"json 数组元素:%@",string);
	}
	[jd release];
	return array;
}

- (NSDictionary *)sampleJsonToDictionary
{
	JSONDecoder *jd=[[JSONDecoder alloc] init];
	
	NSString *json = [self sampleDicTojson];
	
	NSDictionary *dic = [jd objectWithUTF8String:(const unsigned char *)[json UTF8String] length: (unsigned int)strlen([json UTF8String])];
	
	for (NSString *string in [dic allKeys])
	{
		NSLog(@"json 字典元素:key = %@,value = %@",string,[dic objectForKey:string]);
	}
	
	[jd release];

	return dic;
}



一定要注意点是,其他人介绍的在解析JSON时使用:

NSDictionary *ret2 = [jd objectWithUTF8String:(const unsigned char *)[json UTF8String] length:(unsigned int)[json length]];



上面的代码中,在计算字符串长度是使用了length方法;这个方法会有一些问题就是当json中有中文字符时就会有问题。所以一定要是使用strlen([json UTF8String])来计算长度。

JSONKit中只提供了NSArray和NSDictionary这样简单的对象转换为JSON,但是在实际的开放过程中我们经常需要将自定义的对象和JSON互转,所以下面是本人进行的一些扩展。

三、自定义对象和JSON的互转

在网上找到一些资料,就是JSONAutoSerializer个提供了自定义对象转换为JSON,就是先将对象转换为NSDictionary,后转换为JSON,但是仍然存在一些缺陷:

a.将对象转换为NSDictionary,而讲NSDictionary转换为JSON使用了其他的库,效率并不高。

b.这个类仅支持自定义类中属性为对象类型的类。

c.这个类并不支持讲JSON转换回对象。

针对以上几点,我做了一些优化。

1.将对象转换为JSON的代码如下:


- (NSString *)serializeObject:(id)theObject
{
    NSString *className = NSStringFromClass([theObject class]);
    
    const char *cClassName = [className UTF8String];
    
    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_t property = properties[i];
        
        NSString *propertyNameString = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding]; 
        
        [propertyNames addObject:propertyNameString];
        
        [propertyNameString release];
        
    }
    
    NSMutableDictionary *finalDict = [[NSMutableDictionary alloc] initWithCapacity:1];
    
    for(NSString *key in propertyNames)
    {
//        SEL selector = NSSelectorFromString(key);
//        id value = [theObject performSelector:selector];
	id value = [theObject valueForKey:key];//这是修改过的
        
        if (value == nil)
        {
            value = [NSNull null];
        }
        
        [finalDict setObject:value forKey:key];
    }
    

	NSString *retString = [finalDict JSONString];
	
	[propertyNames release];

    [finalDict release];
    
    return retString;

}



2.将转换后的JSON还原为对象

- (id)reverseJSON:(NSString *)jsonStr toClassObject:(Class)cClass;
{
	JSONDecoder *jd = [[JSONDecoder alloc]init];
	
	NSDictionary *retDic = [jd objectWithUTF8String:(const unsigned char *)[jsonStr UTF8String]
						 length:(unsigned int)strlen([jsonStr UTF8String])];
	
	id resultObject = [[[cClass alloc] init] autorelease];
	
	NSArray *keys = [retDic allKeys];
	
	for (NSString *key in keys)
	{
		@try
		{
			[resultObject setValue:[retDic objectForKey:key]
					forKey:[NSString stringWithFormat:@"%@",key]];
		}
		@catch (NSException *exception)
		{
			NSLog(@"%@",exception);
		}
	}
	
	[jd release];
	
	return  resultObject;
}



这一部分是我自己写的,如果有什么问题可以留言,大家交流一下。