简介:
客户端和服务器之间进行数据交互时,服务器往往会返回给客户端一定格式的数据。一般而言,服务器返回给客户端的数据为JSON或者XML文档格式的数据(文件下载除外)。下面就针对于这两种数据格式分别介绍。
(一)JSON数据解析:
特点:
JSON来自民间,是一种轻量级的数据格式。 特点是:体积小,传输快,所以百分之八十的数据都是用JSON格式。
格式:
JSON的格式很像OC中的字典和数组,例如:
{"name" : "jack", "age" : 10}
{"names" : ["jack", "rose", "jim"]}
----------------JSON-------------- | ------------------OC------------------ |
------------大括号 { }------------- | -------- [email protected]{}--------- |
------------中括号 [ ]-------------- | [email protected][]------------- |
------------双引号 " "-------------- | [email protected]""------------ |
------ ---数字 10、10.8----------- | [email protected]、@10.8------ |
需要注意的几点:
1.标准格式的JSON:key必须用双引号
2.true/false转换成OC数据后是NSNumber类型。true-->@1;false-->@0
3.null-->NSNull(空对象)
验证方法:
// 字符串 NSString *json = @"null"; // 字符串->二进制数据 NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding]; // 二进制数据->JSON数据 id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; NSLog(@"%@", [obj class]); /* 打印结果: 2015-08-28 00:23:04.393 JSON和OC对象相互转换[6274:345722] NSNull */
JSON数据解析方案:
在iOS中,JSON的常见解析方案有4种,这4种解析方案可以分为两类。
第一类:第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
第二类:苹果原生(自带):NSJSONSerialization(性能最好)
NSJSONSerialization的常见两个方法:
JSON数据(NSData) -> OC对象(Foundation Object)
// JSON数据 -> OC对象 + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
- NSJSONReadingOptions
- NSJSONReadingMutableContainers = (1UL << 0)
- 创建出来的数组和字典就是可变
- NSJSONReadingMutableLeaves = (1UL << 1)
- 数组或者字典里面的字符串是可变的, iOS7以后无效
- NSJSONReadingAllowFragments
- 允许解析出来的对象不是字典或者数组,比如直接是字符串或者NSNumber
- NSJSONReadingMutableContainers = (1UL << 0)
OC对象(Foundation Object)-> JSON数据(NSData)
// OC对象 ->JSON数据 + (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
JSON在线解析地址:
http://tool.oschina.net/codeformat/json
http://json.parser.online.fr/
复杂JSON数据解析:
// 用模型的的ID接收字典中的key为id的value(需要导入MJExtension) [WSVideos setupReplacedKeyFromPropertyName:^NSDictionary *{ return @{@"ID":@"id"}; }]; // 1.创建URL NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"]; // 2.根据URL创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.利用NSURLConnection发送 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (!data) { [self.tableView reloadData]; }else{ // 把json数据解析成oc数据 id res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",res); if ([res isKindOfClass:[NSArray class]]) { NSLog(@"array"); }else if ([res isKindOfClass:[NSDictionary class]]) { NSLog(@"dict"); // 把oc数据转换成数据模型 // 把数据模型保存到模型数组 self.videos = [WSVideos objectArrayWithKeyValuesArray:res[@"videos"]]; } // 刷新表格(发送异步请求,拿到数据后一定要刷新表格) [self.tableView reloadData]; } }];
(二)XML数据解析:
全称是Extensible Markup Language,译作“可扩展标记语言”。一般也叫XML文档(XML Document)。
特点:
--
格式:
一个常见的XML文档一般由以下部分组成:
1.文档声明
2.元素(Element)
3.属性(Attribute)
1.XML语法 – 文档声明:
在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型
最简单的声明
<?xml version="1.0" ?>
用encoding属性说明文档的字符编码
<?xml version="1.0" encoding="UTF-8" ?>
2.XML语法 – 元素(Element)
一个元素包括了开始标签和结束标签
拥有内容的元素:<video>小黄人</video>
没有内容的元素:<video></video>
没有内容的元素简写:<video/>
一个元素可以嵌套若干个子元素(不能出现交叉嵌套)例如:
<videos>
<video>
<name>小黄人 第01部</name>
<length>30</length>
</video>
</videos>
注意:规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素
3.XML语法 – 属性(Attribute)
一个元素可以拥有多个属性
<video name="小黄人 第01部" length="30" />
video元素拥有name和length两个属性
属性值必须用 双引号"" 或者 单引号‘‘ 括住
实际上,属性表示的信息也可以用子元素来表示,比如
<video>
<name>卑鄙的我 第01部</name>
<length>30</length>
</video>
注意:XML语法 –元素的注意
XML中的所有空格和换行,都会当做具体内容处理
下面两个元素的内容是不一样的
第1个
<video>小黄人</video>
第2个
<video>
小黄人
</video>
XML数据解析方案:
在iOS中,XML的解析方式有2种,分别是SAX和DOM解析。
DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件
解析手段大致分为两类,苹果原生/自带的解析器和第三方框架。
第一类:苹果原生。NSXMLParser,SAX方式解析,使用简单
第二类:第三方框架。libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析
GDataXML:DOM方式解析,由Google开发,基于libxml2
XML解析方式的选择建议:
大文件:NSXMLParser、libxml2
小文件:GDataXML、NSXMLParser、libxml2
因为libxml2是纯C语言的,使用难度大,所以不建议使用。GDataXML是谷歌研发的,解析的特点是一次性将整个XML文档加载进内存,所以不适合大文件的解析。综上所分析,只有苹果自带的NSXMLParser是最常用的。
NSXMLParser使用(SAX方式解析):
特点:
NSXMLParser采取的是SAX方式解析,特点是事件驱动,下面情况都会通知代理
当扫描到文档(Document)的开始与结束
当扫描到元素(Element)的开始与结束
步骤:
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { // 1.根据需要解析的XML数据, 创建NSXMLParser对象 NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; // 2.设置代理, 通过代理方法告诉NSXMLParser, 需要获取哪些元素和哪些属性 parser.delegate = self; // 2.开始解析 [parser parse]; }];
代理方法:
// 只要开始解析XML文档就会调用 - (void)parserDidStartDocument:(NSXMLParser *)parser { } // 只要解析完毕XML文档就会调用 - (void)parserDidEndDocument:(NSXMLParser *)parser { // 刷新UI [self.tableView reloadData]; } // 只要开始解析一个元素就会调用 // elementName : 元素名称 // attributeDict : 元素中的属性 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { if ([elementName isEqualToString:@"videos"]) { return; } XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict]; [self.videos addObject:video]; } // 只要解析完一个元素就会调用 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { } // 解析出现错误时调用 - (void)parser:(NSXMLParser *)parser validationErrorOccurred:(NSError *)validationError { NSLog(@"error"); }
GDataXML使用(DOM方式解析):
配置步骤:
1.导入GDataXML框架,导入libxml2库(iOS8不需要导入)
2.设置libxml2的头文件搜索路径(为了能找到libxml2库的所有头文件)
在Head Search Path中加入/usr/include/libxml2
3.设置链接参数(自动链接libxml2库)
在Other Linker Flags中加入-lxml2
4.由于GDataXML是非ARC的,因此得设置编译参数
使用步骤:
GDataXML中常用的类
GDataXMLDocument:代表整个XML文档
GDataXMLElement:代表文档中的每个元素
使用attributeForName:方法可以获得属性值
// 1、创建URL NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"]; // 2、根据URL创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3、利用NSURLConnection发送请求 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { // 1.创建解析器 GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil]; // 2.获取XML文档的根元素 GDataXMLElement *rootElement = document.rootElement; // 3.获取根元素下的所有子元素 NSArray *allSubElement = [rootElement elementsForName:@"video"]; // 4.遍历子元素,取出属性,转换为模型 for (GDataXMLElement *element in allSubElement) { WSVideos *video = [[WSVideos alloc] init]; video.name = [element attributeForName:@"name"].stringValue; video.ID = @([element attributeForName:@"id"].stringValue.integerValue); video.length = @([element attributeForName:@"length"].stringValue.integerValue); video.image = [element attributeForName:@"image"].stringValue; video.url = [element attributeForName:@"url"].stringValue; [self.videos addObject:video]; } // 刷新表格 [self.tableView reloadData]; }];