第一篇的链接为 自己动手解Json!(IOS利用分治法解析Json)(一)
好了,我们知道,写程序需要一步一步的来,我们今天的任务就是要把 {\"name\":\"zhangsan\",\"age\":26 }
这个Json数据解析成NSDictionary对象 (加入的\是转义字符,因为在字符串中"字符是包裹字符用的,
在"的前面加\程序才知道这个"是字符串中的",而不是用来包裹整个字符串的)
在上一篇中,我们已经抽象出来根据传入的Json字符串与开始寻找的位置,给出下一个所需要查找的字符出现的位置 的方法,
在上述Json字符串中,我们发现,值虽然有字符串对象也有数字,但键都是字符串对象,所以,
我们可以有一个根据传入的Json字符串与开始寻找的位置,找到第一个key值和包裹key值的第二个"的位置,并添加到数组中返回的方法
那么我们为什么要在找到key值的同时还要返回第二个"的位置呢,因为我们知道,程序在解析Json的时候,肯定是循环调用的 基本思路就是
先找到key值,在key值的后面找到value,然后在寻找下一个key
我们在找到key后,也需要判断value的类型,如何判断呢,可以通过包裹key值的第二个"的位置在加2后截取的字符串来判断,如果是数字,那么value就是数字,如果是",那么value就是字符串...
但是我们不是也可以只返回一个key值,然后在根据第一个"的位置加上key值的length就能找到了吗,别忘了,一个还行,如果很多的话,就会有重复代码的问题,这是所有程序员,程序都要避免的问题
分析完了,上代码吧
/*
根据传入的Json字符串与开始寻找的位置,找到第一个key值和包裹key值的第二个"的位置,并添加到数组中返回
开始寻找的位置应该是包裹key值的第一个"的位置,所以beginPostion就是第一个"的位置
eg:
{"name":"zhangsan"} ,那么将会返回 name 和 name 后的"在string中的位置
即array[0]是name array[1]是6
*/
- (NSArray *) findKeyFromString:(NSString *)dicJsonString beginPostion:(int) beginPostion{
//找到包裹key值的第二个"的位置,即从第一个"的下一个字符处开始寻找
int nextSignPostion = [self searchNextSign:'"' formString:dicJsonString beginPostion:beginPostion+1];
//计算出需要截取的长度
int subLenght = nextSignPostion - beginPostion - 1;
//寻找的key值
NSString * key;
//如果是0的话,那么说明""中间没有数据,那么key值是@""
if (subLenght==0) {
key=@"";
}else{
NSRange range = NSMakeRange(beginPostion+1 , subLenght);
//截取出相应的key
key = [dicJsonString substringWithRange:range];
}
//将下一个"的位置封装成NSNumber Object类型
NSNumber * nextPostion = [NSNumber numberWithInt:nextSignPostion];
NSArray * keyArray=[NSArray arrayWithObjects:key,nextPostion ,nil];
return keyArray;
}
寻找key和确定其value类型的方法前面已给出
还有需要注意的是,数组中会有一个指针从头开始向后移动得到key和value,当得到value后,指针会指向value的后一个字符,如果字符是},说明指针指向了最后,那么遍历结束,返回获取的总NSMutableDictionary
上代码(代码中有详细解释)
/*
传入一个NSString类型的Json对象, 将其解析成一个NSMutableDictionary返回
*/
-(NSMutableDictionary *) decodeDicString:(NSString *)dicJsonString{
//初始化一个Dic数组
NSMutableDictionary * decodeDic=[[NSMutableDictionary alloc] init];
//初始位置是指向第一个{
int postion = 0;
long length = [dicJsonString length];
//当postion不指向最后一个},即未到达最后的时候
while (postion!=length-1) {
//先寻找key
NSArray * array = [self findKeyFromString:dicJsonString beginPostion:postion+1];
NSString * key = array[0];
NSNumber * nextPostion = array[1];
//找到value中第一个字符的位置,应该是key中第二个"+2的位置
int valueFirstPostion = nextPostion.intValue+2;
int valueLastPostion;
//截取:之后的第一个字符,看看是数字,还是",
char fristValue = [dicJsonString characterAtIndex:valueFirstPostion];
//如果是数字的话
if (fristValue>=48&&fristValue<=57) {
//先从:后面的开始寻找,先找,如果找到,中间即是数字,如果找不到就说明是最后一个,开始寻找}
valueLastPostion = [self searchNextSign:',' formString:dicJsonString beginPostion:valueFirstPostion];
//如果是-1,说明没找到,这个数是在整个{}的最后面,所以应该valueLastPostion就是长度
//注意长度是从1开始计算的,所以最后一个是长度减1
if (valueLastPostion==-1) {
valueLastPostion = (int) length-1;
}
//得到其中的数据
int intValue = [[dicJsonString substringWithRange:NSMakeRange(valueFirstPostion, valueLastPostion - valueFirstPostion)] intValue];
//添加到NSMutableDictionary中
[decodeDic setObject:[NSNumber numberWithInt:intValue] forKey:key];
//因为是数字,直接指向了数字后面的,号
postion = valueLastPostion;
}
//如果是"的话,那么肯定是字符串
//那么就可以取巧根据寻找key的那个方法来寻找出String类型的value
else if (fristValue=='"'){
NSArray * stringValueArray = [ self findKeyFromString:dicJsonString beginPostion:valueFirstPostion];
NSString * stringValue = stringValueArray[0];
//第二个"的位置
valueLastPostion = [stringValueArray[1] intValue];
//添加到NSMutableDictionary中
[decodeDic setObject:stringValue forKey:key];
//应指向第二个"后面的,或者}
postion = valueLastPostion +1;
}
}
return decodeDic;
}
例如此篇博客头部提到的测试字符串 {\"name\":\"zhangsan\",\"age\":26 }
测试代码:
NSMutableDictionary * dic = [self decodeDicString:@"{\"name\":\"zhangsan\",\"age\":26 }"];
NSLog(@"解析的结果是%@",dic);
测试结果;
解析的结果是{
age = 26;
name = zhangsan;
}