2.JSON&XML

People Lack Willpower,Rather Than Strength!

1.服务器返回的数据:

  • 对于服务器返回来的data,一般有两种格式:JSON/XML

    • JSON:是民间的;
    • XML:是官方的;
    • 不过,JSON体积更小些,所以开发中常用;
  • Parser-解析

    • 为什么要解析?
      • 因为,无论JSON还是XML,这些数据,我们都无法直接使用,因此,这里需要涉及解析(parser)
    • 1.JSON解析:
      • NSJSONSerialization,苹果官方较好用;
    • 2.XML的解析:
      • 2.1解析方式:
        • DOM解析:小文件,把文件整体载入内存;-->libxml2,GDataXML
        • SAX解析:大文件,逐个元素解析;—> NSXMLParser,libxml2
      • 2.2大小文件解析工具选择:
        • 大文件解析工具:NSXMLParser,libxml2;
        • 小文件解析工具:GDataXML,NSXMLParser,libxml2
    • 3.过时的解析方法:JSONKit/SBJSON/TouchJSON都过期了!

2.JSON

JSON与OC对象相互转换

  • JSON2Object

    /*==========================json2objct======================================*/
    
    (void)json2Object
    {
      // JSON-->Object解析
      // 1.创建url
      NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
    
      // 2.request创建
      NSURLRequest  *request = [NSURLRequest requestWithURL:url];
    
      // 3.发送request
      [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
       // 将JSON类型的数据转换为对象
    
       //1.JSON数据对应的对象是什么? 数组还是字典
       NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
       //2015-09-07 16:57:16.204 01-JSON与OC对象相互转换[5269:1996779] {"success":"登录成功"}
       // 可见JSON 数据应该转换成字典对象
    
      // 2.使用NSJSONSerialization转换
      // JSON->Objec方法参数说明:
      // 参数一:需要被转换的JSON数据;
      // 参数二:如何转换JSON数据:转换出来的对象是否可变/子对象是否可变/是否是标准JSON
      // enum说明:
      // NSJSONReadingMutableContainers = 转换出来的对象是可变数组或者可变字典;
      // NSJSONReadingMutableLeaves = 转换出来的OC对象中的字符串是可变的⚠️ iOS7之后无效,有bug;
      // NSJSONReadingAllowFragments = 如果服务器返回的JSON数据,不是标准的JSON,那么就必须使用这个值,否则无法解析;
      // 参数三:错误信息;
      NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    
      NSLog(@"%@",jsonDict);
      /*
       2015-09-07 17:00:13.652 01-JSON与OC对象相互转换[5304:2005870] {
       success = "\U767b\U5f55\U6210\U529f";
       }
       */
        }];
    }
    
  • 标准JSON

    //标准JSON:JSON数据是对应数组/字典对象;
    //如果JSON数据是以下数据:
      //NSString *json = @"10/10.1...";
      // 10-->NSNumber
      //10.1-->NSNumber
      // true/false -->NSNumber;
      //null-->NSNull(空对象)
      //那么此时JSON数据不是标准JSON数据;
    
    // 此时如果想将JSON数据转换成对象,那么:
    // 需要使用NSJSONReadingAllowFragments 参数.否则解析不出来.
    
    id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]
     // 此时系统默认把非标准JSON数据,转换成右边对应对象类型.
    
  • Object2JSON


      // 将对象转换为JSON数据
      // 1.创建字典对象
      NSDictionary *dict = @{
                             @"name":@"xmg",
                             @"age":@20,
                             @"gender":@"man"
                             };

      // 2.将字典对象转换为JSON数据
      /*
       参数说明:
       参数一:需要转换的对象;
       参数二:转换的JSONdata是否需要排版;
       参数三:错误信息;
       */
  //    NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
      NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:nil];

      NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);

      /*排版的!
       2015-09-07 17:33:55.277 01-JSON与OC对象相互转换[5493:2092054] {
       "name" : "xmg",
       "age" : 20,
       "gender" : "man"
       }
       */

      /*不排版的!
       2015-09-07 17:34:36.165 01-JSON与OC对象相互转换[5515:2096109] {"name":"xmg","age":20,"gender":"man"}
       */

MJExtension

  • 目的:将复杂的JSON数据转换成OC对象;

  • 使用步骤:

    • 1.创建需要转换的模型;

      #import <Foundation/Foundation.h>
      
      @interface PJVideo : NSObject
      
      @property (nonatomic , copy) NSString *name;/**<<#注释#>*/
      @property (nonatomic , copy) NSString *image;/**<<#注释#>*/
      @property (nonatomic , copy) NSString *url;/**<<#注释#>*/
      @property (nonatomic , strong) NSNumber *length;/**<<#注释#>*/
      
      @property (nonatomic , strong) NSNumber *ID;/**<<#注释#>*/
      
      @end
      
    • 2.将JSON数据中特殊的key名字做特殊处理;

          // 设置字典转模型中替换的属性名
          // 只需要在字典转模型之前, 告诉框架要将模型中的哪个属性和字典中的哪个KEY对应
          [PJVideo setupReplacedKeyFromPropertyName:^NSDictionary *{
              return @{@"ID":@"id"};
          }];
      
    • 3.请求JSON数据

      
          // 导入JSON数据
          // 1.创建url
          NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"];
      
          // 2.创建request
          NSURLRequest *request = [NSURLRequest requestWithURL:url];
      
          // 3.发送request
          [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            .....
      
    • 4.将服务器返回的JSON数据转换成我们需要的OC对象

              // 将JSON数据转换成对象
              NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
      
              // self.videos中的所有字典转换为模型❤️
              /*
               优点:
               1.没有任何依赖关系
               2.模型中的属性, 不用和字典中的key一一对应
               */
              self.videos = [PJVideo objectArrayWithKeyValuesArray:jsonDict[@"videos"]];
      
              // 拿到数据之后一定要刷新表格,不然数据刷新不出来!🈲
              // 因为是异步!!!❤️❤️❤️主线程的tableView刷新和请求JSON数据同步进行,等得到JSON数据时,tableView早就刷新完了!!
              [self.tableView reloadData];
      
          }];
      
  • 企业开发中如何查看服务器反馈的JSON数据样式?

    • 1.简单打印查看

      // 查看JSON数据样式
      NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
      

    • 2.http://tool.oschina.net/codeformat/json

    • 3.写入本地文件中个查看

       [dict writeToFile:@"/Users/PlwNs/Desktop/videos.plist" atomically:YES];
      

3.XML

3.1SAX解析-NSXMLParser

  • XML语法-元素:
Snip20150912_3.png
  • 说明:为什么我们需要通过代理方法,才能从XML中解析出我们需要的内容?

    • 从下面的XML代码中,我们可以看出:

      <videos>
          <video name="小黄人 第01部" length="30" />
          <video name="小黄人 第02部" length="19" />
          <video name="小黄人 第03部" length="33" />
      </videos>
      
    • 我们需要解析的数据可能藏在元素内容中,也可能藏在元素属性中;

    • 所以我们需要在代理方法中说明,我们需要怎么解析这些元素,从而取得数据;

  • 解析步骤:

    • 1.创建parser对象;
    • 2.设置代理,通过代理方法告诉NSXMLParser,需要获取哪些元素和那些属性;
    • 3.导入代理协议,实现代理方法;
    • 4.开始解析;
  • 代码示例:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
       [PJVideo setupReplacedKeyFromPropertyName:^NSDictionary *{
            return @{@"ID":@"id"};
        }];
    
        // 导入JSON数据
        // 1.创建url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
    
        // 2.创建request
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
        // 3.发送request
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    
            // 将xml数据转换成对象❤️
            // 1.创建parser对象
            NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
            // 2.设置代理,通过代理方法告诉NSXMLParser,需要获取哪些元素和那些属性
            parser.delegate = self;
            // 3.开始解析
            [parser parse];
    
        }];
    }
    
    /*==========================NSXMLParserDelegate================================*/
    #pragma mark - NSXMLParser
    // 开始解析xml文档
    - (void)parserDidStartDocument:(NSXMLParser *)parser
    {
    //    NSLog(@"%s",__func__);
    }
    // 结束xml文档解析
    - (void)parserDidEndDocument:(NSXMLParser *)parser
    {
        // xml文档完成解析后,刷新表格
        [self.tableView reloadData];
    
    //     NSLog(@"%s",__func__);
    }
    
    // 开始一个元素解析
    // elementName:元素名称
    // attributeDict:属性字典
    // 该方法频繁调用
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
    {
        if ([elementName isEqualToString:@"videos"]) { // 根元素没有内容和属性,无需解析
            return;
        }
    
        // 解析属性字典为模型
        PJVideo *video = [PJVideo objectWithKeyValues:attributeDict];
        // 将模型存入数组
        [self.videos addObject:video];
    
    }
    // 完成一个元素解析
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {//     NSLog(@"%s",__func__);
    }
    // 解析出现错误时调用
    - (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError
    {//     NSLog(@"%s",__func__);
    }
    
    /* 可见解析顺序:文档开始解析-->元素开始解析-->元素结束解析-->文档结束解析
    
     2015-09-07 20:46:49.398 02-复杂JSON数据的解析[7358:2617971] -[ViewController parserDidStartDocument:]
     2015-09-07 20:46:49.398 02-复杂JSON数据的解析[7358:2617971] -[ViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:]
     2015-09-07 20:46:49.398 02-复杂JSON数据的解析[7358:2617971] -[ViewController parser:didStartElement:namespaceURI:qualifiedName:attributes:]
     2015-09-07 20:46:49.399 02-复杂JSON数据的解析[7358:2617971] -[ViewController parser:didEndElement:namespaceURI:qualifiedName:]
    ............
    
     2015-09-07 20:46:49.464 02-复杂JSON数据的解析[7358:2617971] -[ViewController parser:didEndElement:namespaceURI:qualifiedName:]
     2015-09-07 20:46:49.464 02-复杂JSON数据的解析[7358:2617971] -[ViewController parserDidEndDocument:]
     */
    

3.2DOM解析-GDataXML

  • 配置

    • 1.导入libxml2库


      libxml2库.png
  • 2.设置libxml2的头文件搜索路径![配置GDataXML1]


    配置GDataXML1.png
  • 3.设置链接参数(自动链接libxml2库)
配置GDataXML2.png
  • 设置非ARC标记
GDataXML非ARC.png
  • 与SAX解析区别:
    • DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
    • SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件;
  • 使用步骤:

    • 1.创建解析器;
    • 2.获得根元素;
    • 3.从根元素中获得所有子元素;
    • 4.遍历子元素,取出属性转换成模型;
    • 5.将每个模型存入数组;
    • 6.刷新tableView;
  • 代码示例:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // 设置字典转模型中替换的属性名
        // 只需要在字典转模型之前, 告诉框架要将模型中的哪个属性和字典中的哪个KEY对应
        [PJVideo setupReplacedKeyFromPropertyName:^NSDictionary *{
            return @{@"ID":@"id"};
        }];
    
        // 导入JSON数据
        // 1.创建url
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
    
        // 2.创建request
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
        // 3.发送request
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    
          // 1.创建解析器
            GDataXMLDocument *xmlDoc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
            // 2.获得根元素
            GDataXMLElement *rootElement = xmlDoc.rootElement;
            // 3.从根元素中获得所有子元素
            NSArray *elements = [rootElement elementsForName:@"video"]; // 这里video,表示获得所有叫video的子元素
            // 3.遍历子元素,取出属性转换为模型
            for (GDataXMLElement *element in elements) {
    
                PJVideo *video = [[PJVideo alloc] init];
                // 取出元素属性,转换为模型值
                video.ID = @([element attributeForName:@"id"].stringValue.integerValue);
                video.name = [element attributeForName:@"name"].stringValue;
                video.length = @([element attributeForName:@"length"].stringValue.integerValue);
                video.url = [element attributeForName:@"url"].stringValue;
                video.image = [element attributeForName:@"image"].stringValue;
    
                // 保存模型
                [self.videos addObject:video];
    
                // 刷新表格/因为这里异步,所以必然刷新表格
                [self.tableView reloadData];
            }
    
        }];
    }
    

推荐阅读更多精彩内容

  • JSON JSON和XML都是需要解析的 JSON是一种轻量级的数据格式,一般用于数据交互服务器返回给客户端的数据...
    JonesCxy阅读 1,017评论 2 10
  • JSON 和 XML 一、JSON 1.什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互服务器返回...
    妳是我的天使阅读 88评论 0 3
  • JSON 什么是JSON JSON是一种轻量级的数据格式,一般用于数据交互. 服务器返回给客户端的数据,一般都是J...
    coma阅读 88评论 0 1
  • JSON解析 JSON简单介绍 JSON是一种轻量级的数据格式,一般用于数据交互。服务器返回给客户端的数据,一般都...
    搁浅的青蛙阅读 712评论 0 4
  • NSURLSession基本使用 简介 使用步骤使用NSURLSession会话对象创建Task,然后执行Task...
    彼岸的黑色曼陀罗阅读 547评论 0 2