IOS网络(二):URL的中文转码,JSON解析及XML解析

URL的中文转码

如果当URL中还有中文字符时,将会报无法找到URL的错误,解决方式如下:

GET中文转码方法: [@"http://120.25.226.186:32812/login2?username=中文转码&pwd=520it&type=JSON" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]

POST中文转码方法: [@"username=中文转码&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding]

-(void)get
{
    
    NSString *urlStr = @"http://120.25.226.186:32812/login2?username=中文转码&pwd=520it&type=JSON";
    
    NSLog(@"转码前: %@",urlStr);
    
    //中文转码处理
    urlStr =  [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    
    NSLog(@"转码后: %@",urlStr);
    
    //1.url
    NSURL *url = [NSURL URLWithString:urlStr];
    
    //http://120.25.226.186:32812/login2?username=%E5%B0%8F%E7%A0%81%E5%93%A5&pwd=520it&type=JSON
    
    NSLog(@"url------%@",url);
    
    //2.urlrequest
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //3.connect
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        
        
        //容错处理
        if (connectionError) {
            NSLog(@"%@",connectionError);
            return ;
        }
        //4.解析
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];

}

-(void)post
{
    //观察URL中是否有中文,如果有中文则需要转码
    NSString *urlStr = @"http://120.25.226.186:32812/login2";
    
    //username=中文转码&pwd=520it&type=JSON
    //1.url
    NSURL *url = [NSURL URLWithString:urlStr];
    
    //2.urlrequest
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //2.1 post
    request.HTTPMethod = @"POST";
    
    //2.2 body
    request.HTTPBody = [@"username=中文转码&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    
    //3.connect
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        
        //容错处理
        if (connectionError) {
            NSLog(@"%@",connectionError);
            return ;
        }
        //4.解析
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];

}

JSON解析

  • 什么是JSON

   JSON是一种轻量级的数据格式,一般用于数据交互

   服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外)

  • JSON的格式很像OC中的字典和数组

   {"name" : "jack", "age" : 10}

   {"names" : ["jack", "rose", "jim"]}

  • 标准JSON格式的注意点:key必须用双引号
  • 要想从JSON中挖掘出具体数据,得对JSON进行解析(JSON 转换为 OC数据类型)

  • 在iOS中,JSON的常见解析方案有4种

   第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差) 

   苹果原生(自带):NSJSONSerialization(性能最好)

  • NSJSONSerialization的常见方法

   JSON->OC(反序列化): + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;

   OC->JSON(序列化): + (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

  序列化: 将数据结构或对象转换成二进制串的过程。

  反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

  • NSJSONReadingOptions:

        NSJSONReadingMutableContainers = (1UL << 0), 可变字典和数组

        NSJSONReadingMutableLeaves = (1UL << 1),      内部所有的字符串都是可变的, ios7之后有问题,  一般不用

        NSJSONReadingAllowFragments = (1UL << 2)   既不是字典也不是数组,则必须使用该枚举值

  • NSJSONWritingOptions:

        NSJSONWritingPrettyPrinted: 排版 美观

  • 注意:并不是所有的OC对象都能转换为JSON

       最外层必须是 NSArray or NSDictionary

       所有的元素必须是 NSString, NSNumber, NSArray, NSDictionary, or NSNull

       字典中所有的key都必须是 NSString类型的

       NSNumber不能是无穷大

-(void)JSONWithOc
{
    //NSString *strM = @"{\"error\":\"用户名不存在\"}";
    //NSString *strM = @"[\"error\",\"用户名不存在\"]";
    //NSString *strM = @"\"wendingding\"";
    //NSString *strM = @"false";
    //NSString *strM = @"true";
    NSString *strM = @"null";
    
    id obj = [NSJSONSerialization JSONObjectWithData:[strM dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:0];
    NSLog(@"%@---%@",[obj class],obj);
    
    /*
     JOSN   OC
     {}     @{}
     []     @[]
     ""     @""
     false  NSNumber 0
     true   NSNumber 1
     null      NSNull为空
     */
    
    //nil
    [NSNull null];   //该方法获得的是一个单例,表示为空,可以用在字典或者是数组中
    
}

//OC--->json
-(void)OCtojson
{
    NSDictionary *dictM = @{
                            @"name":@"dasheng11",
                            @"age":@3
           };
    
    NSArray *arrayM = @[@"123",@"456"];
    
    //注意:并不是所有的OC对象都能转换为JSON
    /*
     - 最外层必须是 NSArray or NSDictionary
     - 所有的元素必须是 NSString, NSNumber, NSArray, NSDictionary, or NSNull
     - 字典中所有的key都必须是 NSStrings类型的
     - NSNumbers不能死无穷大
     */
    NSString *strM = @"WENIDNGDING";
    
    //判断OC对象是否能转化为JSON
    BOOL isValid = [NSJSONSerialization isValidJSONObject:strM];
    if (!isValid) {
        NSLog(@"%d",isValid);
        return;
    }
    
    //OC--->json
    /*
     第一个参数:要转换的OC对象
     第二个参数:选项NSJSONWritingPrettyPrinted 排版 美观
     */
    NSData *data = [NSJSONSerialization dataWithJSONObject:strM options:NSJSONWritingPrettyPrinted error:nil];
    
    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}

XML解析

  • 一个常见的XML文档一般由以下部分组成

       文档声明

       元素(Element)

       属性(Attribute)

  • XML语法 – 文档声明: 在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型

       最简单的声明: <?xml version="1.0" ?>

       用encoding属性说明文档的字符编码: <?xml version="1.0" encoding="UTF-8" ?>

  • XML语法 – 元素(Element)
  1.  一个元素包括了开始标签和结束标签

       拥有内容的元素:<video>小黄人</video>

       没有内容的元素:<video></video>

       没有内容的元素简写:<video/>

     2.   一个元素可以嵌套若干个子元素(不能出现交叉嵌套)

<videos>

    <video>

        <name>小黄人 第01部</name>

         <length>30</length>

    </video>

</videos>
  • 规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素
  • XML语法 –元素的注意
  1. XML中的所有空格和换行,都会当做具体内容处理
  2. 下面两个元素的内容是不一样的

    第1个: <video>小黄人</video>

    第2个: <video>

                         小黄人

                 </video>

  • XML语法 – 属性(Attribute)
  1. 一个元素可以拥有多个属性
  • <video name="小黄人 第01部" length="30" />

  • video元素拥有name和length两个属性
  • 属性值必须用 双引号"" 或者 单引号'' 括住
  •  实际上,属性表示的信息也可以用子元素来表示,比如
  • <video>

        <name>小黄人 第01部</name>

            <length>30</length>

    </video>

  • XML解析方法

       1.  要想从XML中提取有用的信息,必须得学会解析XML

       2. 提取name元素里面的内容

  •       <name>小黄人 第01部</name>

  • 3. 提取video元素中name和length属性的值

  •      <video name="小黄人 第01部" length="30" />

        4.  XML的解析方式有2种:

             DOM:一次性将整个XML文档加载进内存,比较适合解析小文件

             SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件


iOS中的XML解析

  • 在iOS中,解析XML的手段有很多
  • 苹果原生

        NSXMLParser:SAX方式解析,使用简单

  •  第三方框架

        libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析

        GDataXML:DOM方式解析,由Google开发,基于libxml2

  • XML解析方式的选择建议

       大文件:NSXMLParser、libxml2

       小文件:GDataXML、NSXMLParser、libxml2


NSXMLParser

  • 使用步骤
// 传入XML数据,创建解析器

NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];

// 设置代理,监听解析过程

parser.delegate = self;

// 开始解析

[parser parse];
  • NSXMLParser采取的是SAX方式解析,特点是事件驱动,下面情况都会通知代理

       1. 当扫描到文档(Document)的开始与结束

       2. 当扫描到元素(Element)的开始与结束

NSXMLParserDelegate

  • 当扫描到文档的开始时调用(开始解析)
- (void)parserDidStartDocument:(NSXMLParser *)parser
  • 当扫描到文档的结束时调用(解析完毕)
- (void)parserDidEndDocument:(NSXMLParser *)parse
  • 当扫描到元素的开始时调用(attributeDict存放着元素的属性)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
  •  当扫描到元素的结束时调用
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName

NSXMLParser

  • GDataXML基于libxml2库,得做以下配置
  1. 导入libxml2库

  • 设置libxml2的头文件搜索路径(为了能找到libxml2库的所有头文件)

       在Head Search Path中加入/usr/include/libxml2

  • 设置链接参数(自动链接libxml2库)

        在Other Linker Flags中加入-lxml2

  •  GDataXML配置

         由于GDataXML是非ARC的,因此得设置编译参数

  • GDataXML使用

      GDataXML中常用的类

      1.  GDataXMLDocument:代表整个XML文档

      2. GDataXMLElement : 代表文档中的每个元素;使用attributeForName:方法可以获得属性值

  • JSON和XML比较

同一份数据,既可以用JSON来表示,也可以用XML来表示

相比之下,JSON的体积小于XML,所以服务器返回给移动端的数据格式以JSON居多。

猜你喜欢

转载自blog.csdn.net/weixin_42433480/article/details/89684465