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
- DOM解析:小文件,把文件整体载入内存;-->libxml2,
- 2.2大小文件解析工具选择:
- 大文件解析工具:NSXMLParser,libxml2;
- 小文件解析工具:GDataXML,NSXMLParser,libxml2
- 2.1解析方式:
- 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]);
-
3.写入本地文件中个查看
[dict writeToFile:@"/Users/PlwNs/Desktop/videos.plist" atomically:YES];
-
3.XML
3.1SAX解析-NSXMLParser
- XML语法-元素:
-
说明:为什么我们需要通过代理方法,才能从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库
-
-
2.设置libxml2的头文件搜索路径![配置GDataXML1]
- 3.设置链接参数(自动链接libxml2库)
- 设置非ARC标记
- 与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]; } }]; }