美文网首页
2.JSON&XML

2.JSON&XML

作者: SoftKnife | 来源:发表于2015-10-05 13:48 被阅读214次
    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];
              }
      
          }];
      }
      

    相关文章

      网友评论

          本文标题:2.JSON&XML

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