自己动手解Json!(IOS利用分治法解析Json)(三)

本文介绍了如何通过递归方法解析包含嵌套对象的JSON字符串,例如:{""name"":""zhang"


 上一次我们已经解析出了 {\"name\":\"zhangsan\",\"age\":26 } 这种最基础的json字符串,那么这一次就需要解析带有{}这种对象括号的

json字符串了

那么,这一次的任务就是解析出@"{\"name\":\"zhang\",\"learn\":{\"school\":{\"name\":\"wudaokou\"}},\"age\":18}"这个

json字符串,

可以看到,在learn指向的{}里面,还有一个{}value,这该怎么解析呢,当然是用我们的递归方法了大笑 别忘了我们一开始的方法就是传入一个

json字符串,然后解析字符串为字典value,相应的,这个也是,在解析最外层的字典value时,需要得到learn所指向的字典value,在解析leaen所

指向的字典value时,需要得到school所指向的字典value,

这时候,我们的解决方法就是当发现value是字典的时候,得到这个字典所包括的全部json字符串,然后调用自己解析json字符串的方法

返回一个字典value

方法有了,这时候又有一个问题,我们如何得到这个字典所包括的全部json字符串呢,如果只有一个 "learn":{"school":"wudaokou"},

那非常的简单,找到第一个{的位置的时候,寻找下一个}的位置即可,然后把{与}之间的内容全部都截取下来

可是对于我们最上面要解析出来的字符串可不能这样,否则会出错,

这时候的方法就是,从字典value的第一个{开始遍历整个json字符串,如果有{,leftSignSunm++ , 如果有}

rightSignSum++ ,当 rightSignSum == leftSignSunm+1的时候,就说明找到了

好了,贴出上述方法的代码:

/*
 
 根据传入的Json字符串与开始寻找的位置,找到 {} 的这个 value值,和value第二个 } 的位置 ,并添加到数组中返回
 
 开始寻找到的位置beginPostion是{ ... } 左边的那个{
 
 eg: {"name":"zhang","learn":{"school":{"name":"wudaokou"}},"age":18}
 
 返回的array[0]是{"school":{"name":"wudaokou"}}  array[1]是53,即第二个}的位置
 
 */
-(NSArray *) findNextRightBracketAppearPostionFromString:(NSString *)dicJsonString beginPostion:(int) beginPostion{
    
    //得到数组长度
    long length = [dicJsonString length];
    
    //记录左边那个符号的总数
    int leftSignSunm = 0;
    
    //记录右边那个符号的总数
    int rightSignSum=0;
    
    char postionChar;
    
    NSString * subDicJsonString;
    
    NSNumber * rightPostion;
    
    for (int findPostion = beginPostion+1; findPostion<length; findPostion++) {
        
        postionChar = [dicJsonString characterAtIndex:findPostion];
        
        if (postionChar == '{') {
            leftSignSunm++;
        }
        
        if (postionChar == '}') {
            rightSignSum++;
        }
        
        //如果}的总数等于{的总数加一的话,说明找到了
        if (rightSignSum == leftSignSunm+1) {
            
            //将需要的截取出来,然后结束循环
            
            int subLenght = findPostion - beginPostion + 1;
            
            NSRange range = NSMakeRange(beginPostion , subLenght);
            
            subDicJsonString = [dicJsonString substringWithRange:range];
            
            rightPostion = [NSNumber numberWithInt:findPostion];
            
            break;
            
        }
        
    }
    
    NSArray * valueArray = [NSArray  arrayWithObjects:subDicJsonString,rightPostion, nil];
    
    return valueArray;
    
    
}

这么着,在解析json的时候,如果发现value是{},那么就调用上述方法,截取出json字符串,然后调用自己


贴出修改后的解析json方法:

/*
 传入一个Json字符串 将其解析成一个NSDictionary返回
 */
-(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;
            
            
        }
        //如果都不是的话,那么就应该是{}了
        else{
            
            NSArray * array = [self findNextRightBracketAppearPostionFromString:dicJsonString beginPostion:valueFirstPostion];
            
            NSString * childJsonString=array[0];
            
            valueLastPostion = [array[1] intValue];
            
            //调用自己返回一个对象
            NSDictionary * childDic = [self decodeDicString:childJsonString];
            
            //添加到NSMutableDictionary中
            [decodeDic setObject:childDic  forKey:key];
            
            //应指向}后面的,或者}
            postion = valueLastPostion + 1;
            
            
        }
        
        
    }
    
    
    return decodeDic;
}


这时候,在主方法中测试

NSDictionary * dic = [self decodeDicString:testString];
NSLog(@"结果是%@",dic);


测试结果为

结果是{

    age = 18;

    learn =     {

        school =         {

            name = wudaokou;

        };

    };

    name = zhang;

}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值