05.iOS JSON,XML数据解析

作者: Liwx | 来源:发表于2016-01-16 01:37 被阅读721次

    @(〓〓 iOS-实用技术)[JSON/XML 数据解析]


    目录

    • 05.iOS JSON,XML数据解析
    • 1.JSON数据解析
      • 1.1 NSJSONSerialization解析
      • 1.2 JSONKit解析
      • 1.3 SBJson解析
      • 1.4 TouchJSon解析
    • 2.XML数据解析
      • 2.1 NSXMLParser代理方式解析XML数据
      • 2.2 GDataXML解析XML
        • 使用GDataXML框架设置步骤,具体步骤看截图
        • 使用Google的GDataXML框架解析XML

    1.JSON数据解析

    本文JSON数据解析将介绍TouchJson、SBJson 、JSONKit和iOS5所支持的原生的json方法,解析国家气象局API,TouchJson和SBJson需要下载他们的库.

    • 国家气象局提供的天气预报接口

    接口地址有两个:
    http://www.weather.com.cn/data/sk/101010100.html
    http://www.weather.com.cn/data/cityinfo/101010100.html

    • 四种JSON解析方式效率

    解析速度由高到低: NSJSONSerialization -> JSONKit -> SBJson -> TouchJSon


    1.1 NSJSONSerialization解析

    • 1.使用IOS5自带解析类NSJSONSerialization方法解析
    - (IBAction)btnPressIOS5Json:(id)sender {  
    
        NSError *error;  
        //加载一个NSURL对象  
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://m.weather.com.cn/data/101180601.html"]];  
        //将请求的url数据放到NSData对象中  
        NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];  
        //IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中  
        NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];  
        NSDictionary *weatherInfo = [weatherDic objectForKey:@"weatherinfo"];  
        txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气状况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];  
        NSLog(@"weatherInfo字典里面的内容为--》%@", weatherDic );  
    
    }  
    

    1.2 JSONKit解析

    • 1.使用JSONKit的解析方法:(需导入包:#import "JSONKit/JSONKit.h")
    - (IBAction)btnPressJsonKit:(id)sender {  
          
        //如果json是“单层”的,即value都是字符串、数字,可以使用objectFromJSONString  
        NSString *json1 = @"{\"a\":123, \"b\":\"abc\"}";  
        NSLog(@"json1:%@",json1);  
        NSDictionary *data1 = [json1 objectFromJSONString];  
        NSLog(@"json1.a:%@",[data1 objectForKey:@"a"]);  
        NSLog(@"json1.b:%@",[data1 objectForKey:@"b"]);  
        [json1 release];  
        
        //如果json有嵌套,即value里有array、object,如果再使用objectFromJSONString,程序可能会报错(测试结果表明:使用由网络或得到的php/json_encode生成的json时会报错,但使用NSString定义的json字符串时,解析成功),最好使用objectFromJSONStringWithParseOptions:  
        NSString *json2 = @"{\"a\":123, \"b\":\"abc\", \"c\":[456, \"hello\"], \"d\":{\"name\":\"张三\", \"age\":\"32\"}}";  
        NSLog(@"json2:%@", json2);  
        NSDictionary *data2 = [json2 objectFromJSONStringWithParseOptions:JKParseOptionLooseUnicode];  
        NSLog(@"json2.c:%@", [data2 objectForKey:@"c"]);  
        NSLog(@"json2.d:%@", [data2 objectForKey:@"d"]);  
        [json2 release];  
    
    } 
    

    1.3 SBJson解析

    • 1.使用SBJson解析方法:(需导入包:#import "SBJson/SBJson.h")
    //使用SBJson解析南阳的天气  
    - (IBAction)btnPressSBJson:(id)sender {  
    
        NSURL *url = [NSURL URLWithString:@"http://m.weather.com.cn/data/101180701.html"];  
        NSError *error = nil;  
        NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];  
        SBJsonParser *parser = [[SBJsonParser alloc] init];  
        
        NSDictionary *rootDic = [parser objectWithString:jsonString error:&error];  
        NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];  
        txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气状况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];  
    
    }  
    

    1.4 TouchJSon解析

    • 1.使用TouchJSon解析方法:(需导入包:#import "TouchJson/JSON/CJSONDeserializer.h")
    //使用TouchJson来解析北京的天气  
    - (IBAction)btnPressTouchJson:(id)sender {  
    
        //获取API接口  
        NSURL *url = [NSURL URLWithString:@"http://m.weather.com.cn/data/101010100.html"];  
        //定义一个NSError对象,用于捕获错误信息  
        NSError *error;  
        NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];  
        NSLog(@"jsonString--->%@",jsonString);  
        
        //将解析得到的内容存放字典中,编码格式为UTF8,防止取值的时候发生乱码  
        NSDictionary *rootDic = [[CJSONDeserializer deserializer] deserialize:[jsonString dataUsingEncoding:NSUTF8StringEncoding] error:&error];  
        //因为返回的Json文件有两层,去第二层内容放到字典中去  
        NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];  
        NSLog(@"weatherInfo--->%@",weatherInfo);  
        //取值打印  
        txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气状况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];  
          
    }  
    

    2.XML数据解析

    2.1 NSXMLParser代理方式解析XML数据

    • 1.NSXMLParser常用代理方法
    #pragma mark - <NSXMLParserDelegate>
    // SINGLE: 当开始解析XML文档的时候调用,只调用一次
    - (void)parserDidStartDocument:(NSXMLParser *)parser;
    
    // SINGLE: 开始解析某个元素的时候调用,如果有多个元素,会调用多次,调用一次解析一个元素
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict;
    
    // SINGLE: 结束解析某个元素的时候调用,会调用多次
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
    
    // SINGLE: 整个XML文档解析结束的时候调用
    - (void)parserDidEndDocument:(NSXMLParser *)parser;
    
    • 2.使用NSXMLParser解析XML数据
      • 开启XML数据解析 [parser parse];
    // REMARKS: 解析XML数据,使用NSXMLParser代理方式解析XML数据
    - (void)netWork
    {
        // 创建请求数据的url路径,XML格式的数据
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
        
        // 创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        // 发送GET请求,异步
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
            
            // REMARKS: 解析XML数据,使用NSXMLParser代理方式解析XML数据
            NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
            
            // 设置代理
            parser.delegate = self;
            
            // SINGLE: 开始解析 该方式是阻塞的
            [parser parse];
            
            // 刷新tableView数据
            [self.tableView reloadData];
            
        }];
    }
    
    #pragma mark - <NSXMLParserDelegate>
    // SINGLE: 当开始解析XML文档的时候调用,只调用一次
    - (void)parserDidStartDocument:(NSXMLParser *)parser
    {
        NSLog(@"parserDidStartDocument");
    }
    
    // SINGLE: 开始解析某个元素的时候调用,如果有多个元素,会调用多次,调用一次解析一个元素
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
    {
    //    NSLog(@"didStartElement: %@ --- %@", elementName, attributeDict);
        
        // SINGLE: 通过以上打印结果观察,服务器返回的数据中,key为videos的元素(根元素)是数组,所以不能将其添加到数据源数组中,只能添加数组中的元素
        if ([elementName isEqualToString:@"videos"]) {
            return ;
        }
        
        // SINGLE: 使用MJExtension框架将attributeDict字典转模型,
        WXVideo *video = [[WXVideo alloc] init];
        [video mj_setKeyValues:attributeDict];
        [self.videos addObject:video];
    }
    
    // SINGLE: 结束解析某个元素的时候调用,会调用多次
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
    //    NSLog(@"didEndElement --- %@", elementName);
    }
    
    // SINGLE: 整个XML文档解析结束的时候调用
    - (void)parserDidEndDocument:(NSXMLParser *)parser
    {
        NSLog(@"parserDidEndDocument");
    }
    

    2.2 GDataXML解析XML

    使用GDataXML框架设置步骤,具体步骤看截图

    • 使用GDataXML框架解析XML文件时,编译错误解决方案'libxml/tree.h' file not found
    01.GDataXML编译错误解决方案.png
    • 设置GDataXML的编译环境为非ARC环境
    02.GDataXML的编译环境为非ARC环境.png
    • 设置Other Linker Flags,添加一项 -lxml2
    03.Other Linker Flags,添加一项 -lxml2.png

    使用Google的GDataXML框架解析XML

    • 1.使用Google的GDataXML框架解析XML,用GDataXML框架解析XML数据,GDataXML会一次性把整个XML加载到内存,内存短时间内会增大,如果XML数据量大不推荐使用
    // 一次性加载整个XML文档
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
    

    • 2.GDataXML框架解析XML

      • 获取XML的根元素,拿到所有名称叫做video的子元素,该例子的XML根元素为数组,所以用数组接收.

      NSArray *eleArray = [doc.rootElement elementsForName:@"video"];

    // REMARKS: GET方法异步请求cell数据
    - (void)netWork
    {
        // 创建请求数据的url路径,XML格式的数据
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
        
        // 创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        // 发送GET请求,异步
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
            
            // REMARKS: 使用Google的GDataXML框架解析XML,用GDataXML框架解析XML数据,GDataXML会一次性把整个XML加载到内存,内存短时间内会增大,如果XML数据量大不推荐使用
            // 一次性加载整个XML文档
            GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
            
            // SINGLE: 获取XML的根元素,拿到所有名称叫做video的子元素,该例子的XML根元素为数组
            NSArray *eleArray = [doc.rootElement elementsForName:@"video"];
            
            for (GDataXMLElement *ele in eleArray) {
                WXVideo *video = [[WXVideo alloc] init];
                
                // 逐个解析每个属性元素
                video.name = [ele attributeForName:@"name"].stringValue;
                video.image = [ele attributeForName:@"image"].stringValue;
                video.url = [ele attributeForName:@"url"].stringValue;
                video.ID = [ele attributeForName:@"id"].stringValue;
                video.length = [ele attributeForName:@"length"].stringValue;
                
                // 将解析好的模型添加到数据源数组
                [self.videos addObject:video];
            }
            
            // 刷新tableView数据
            [self.tableView reloadData];
            
        }];
    }
    

    相关文章

      网友评论

      • feng_dev:建议楼主把 SBJSON 和 TouchJSON 都删除了吧, 现在 github上面 好像就剩 JSONKit 了, 其他的好像都下架了,写这个没啥用,还误导新手,比如我。。。
        XML 这种的 数据解析 现在是不是 几乎 没人用了。。。
        彦子凡:XML解析还是很有用的,老一点的公司还是很多

      本文标题:05.iOS JSON,XML数据解析

      本文链接:https://www.haomeiwen.com/subject/eqphkttx.html