@(〓〓 iOS-实用技术)[JSON/XML 数据解析]
- 作者: Liwx
- 邮箱: [email protected]
目录
- 05.iOS JSON,XML数据解析
- 1.JSON数据解析
- 1.1 NSJSONSerialization解析
- 1.2 JSONKit解析
- 1.3 SBJson解析
- 1.4 TouchJSon解析
- 2.XML数据解析
- 2.1 NSXMLParser代理方式解析XML数据
- 2.2 GDataXML解析XML
- 使用GDataXML框架设置步骤,具体步骤看截图
- 使用Google的GDataXML框架解析XML
1.JSON数据解析
本文JSON数据解析将介绍TouchJson、SBJson 、JSONKit和iOS5所支持的原生的json方法,解析国家气象局API,TouchJson和SBJson需要下载他们的库.
- 国家气象局提供的天气预报接口
接口地址有两个:
http://www.weather.com.cn/data/sk/101010100.html
http://www.weather.com.cn/data/cityinfo/101010100.html
- 四种JSON解析方式效率
解析速度
由高到低: NSJSONSerialization -> JSONKit -> SBJson -> TouchJSon
1.1 NSJSONSerialization解析
- 1.使用IOS5自带解析类NSJSONSerialization方法解析
- (IBAction)btnPressIOS5Json:(id)sender {
NSError *error;
//加载一个NSURL对象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://m.weather.com.cn/data/101180601.html"]];
//将请求的url数据放到NSData对象中
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
//IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
NSDictionary *weatherInfo = [weatherDic objectForKey:@"weatherinfo"];
txtView.text = [NSString stringWithFormat:@"今天是 %@ %@ %@ 的天气状况是:%@ %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
NSLog(@"weatherInfo字典里面的内容为--》%@", weatherDic );
}
1.2 JSONKit解析
- 1.使用JSONKit的解析方法:(需导入包:#import "JSONKit/JSONKit.h")
- (IBAction)btnPressJsonKit:(id)sender {
//如果json是“单层”的,即value都是字符串、数字,可以使用objectFromJSONString
NSString *json1 = @"{\"a\":123, \"b\":\"abc\"}";
NSLog(@"json1:%@",json1);
NSDictionary *data1 = [json1 objectFromJSONString];
NSLog(@"json1.a:%@",[data1 objectForKey:@"a"]);
NSLog(@"json1.b:%@",[data1 objectForKey:@"b"]);
[json1 release];
//如果json有嵌套,即value里有array、object,如果再使用objectFromJSONString,程序可能会报错(测试结果表明:使用由网络或得到的php/json_encode生成的json时会报错,但使用NSString定义的json字符串时,解析成功),最好使用objectFromJSONStringWithParseOptions:
NSString *json2 = @"{\"a\":123, \"b\":\"abc\", \"c\":[456, \"hello\"], \"d\":{\"name\":\"张三\", \"age\":\"32\"}}";
NSLog(@"json2:%@", json2);
NSDictionary *data2 = [json2 objectFromJSONStringWithParseOptions:JKParseOptionLooseUnicode];
NSLog(@"json2.c:%@", [data2 objectForKey:@"c"]);
NSLog(@"json2.d:%@", [data2 objectForKey:@"d"]);
[json2 release];
}
1.3 SBJson解析
- 1.使用SBJson解析方法:(需导入包:#import "SBJson/SBJson.h")
//使用SBJson解析南阳的天气
- (IBAction)btnPressSBJson:(id)sender {
NSURL *url = [NSURL URLWithString:@"http://m.weather.com.cn/data/101180701.html"];
NSError *error = nil;
NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *rootDic = [parser objectWithString:jsonString error:&error];
NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
txtView.text = [NSString stringWithFormat:@"今天是 %@ %@ %@ 的天气状况是:%@ %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
}
1.4 TouchJSon解析
- 1.使用TouchJSon解析方法:(需导入包:#import "TouchJson/JSON/CJSONDeserializer.h")
//使用TouchJson来解析北京的天气
- (IBAction)btnPressTouchJson:(id)sender {
//获取API接口
NSURL *url = [NSURL URLWithString:@"http://m.weather.com.cn/data/101010100.html"];
//定义一个NSError对象,用于捕获错误信息
NSError *error;
NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
NSLog(@"jsonString--->%@",jsonString);
//将解析得到的内容存放字典中,编码格式为UTF8,防止取值的时候发生乱码
NSDictionary *rootDic = [[CJSONDeserializer deserializer] deserialize:[jsonString dataUsingEncoding:NSUTF8StringEncoding] error:&error];
//因为返回的Json文件有两层,去第二层内容放到字典中去
NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
NSLog(@"weatherInfo--->%@",weatherInfo);
//取值打印
txtView.text = [NSString stringWithFormat:@"今天是 %@ %@ %@ 的天气状况是:%@ %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
}
2.XML数据解析
2.1 NSXMLParser代理方式解析XML数据
- 1.NSXMLParser常用代理方法
#pragma mark -
// SINGLE: 当开始解析XML文档的时候调用,只调用一次
- (void)parserDidStartDocument:(NSXMLParser *)parser;
// SINGLE: 开始解析某个元素的时候调用,如果有多个元素,会调用多次,调用一次解析一个元素
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
// SINGLE: 结束解析某个元素的时候调用,会调用多次
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
// SINGLE: 整个XML文档解析结束的时候调用
- (void)parserDidEndDocument:(NSXMLParser *)parser;
- 2.使用NSXMLParser解析XML数据
- 开启XML数据解析
[parser parse];
- 开启XML数据解析
// REMARKS: 解析XML数据,使用NSXMLParser代理方式解析XML数据
- (void)netWork
{
// 创建请求数据的url路径,XML格式的数据
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
// 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 发送GET请求,异步
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// REMARKS: 解析XML数据,使用NSXMLParser代理方式解析XML数据
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 设置代理
parser.delegate = self;
// SINGLE: 开始解析 该方式是阻塞的
[parser parse];
// 刷新tableView数据
[self.tableView reloadData];
}];
}
#pragma mark -
// SINGLE: 当开始解析XML文档的时候调用,只调用一次
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidStartDocument");
}
// SINGLE: 开始解析某个元素的时候调用,如果有多个元素,会调用多次,调用一次解析一个元素
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
// NSLog(@"didStartElement: %@ --- %@", elementName, attributeDict);
// SINGLE: 通过以上打印结果观察,服务器返回的数据中,key为videos的元素(根元素)是数组,所以不能将其添加到数据源数组中,只能添加数组中的元素
if ([elementName isEqualToString:@"videos"]) {
return ;
}
// SINGLE: 使用MJExtension框架将attributeDict字典转模型,
WXVideo *video = [[WXVideo alloc] init];
[video mj_setKeyValues:attributeDict];
[self.videos addObject:video];
}
// SINGLE: 结束解析某个元素的时候调用,会调用多次
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(@"didEndElement --- %@", elementName);
}
// SINGLE: 整个XML文档解析结束的时候调用
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidEndDocument");
}
2.2 GDataXML解析XML
使用GDataXML框架设置步骤,具体步骤看截图
- 使用GDataXML框架解析XML文件时,编译错误解决方案'libxml/tree.h' file not found
- 设置GDataXML的编译环境为非ARC环境
- 设置Other Linker Flags,添加一项 -lxml2
使用Google的GDataXML框架解析XML
- 1.使用Google的GDataXML框架解析XML,用GDataXML框架解析XML数据,GDataXML会一次性把整个XML加载到内存,内存短时间内会增大,如果XML数据量大不推荐使用
// 一次性加载整个XML文档
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
-
2.GDataXML框架解析XML
- 获取XML的根元素,拿到所有名称叫做video的子元素,该例子的XML根元素为数组,所以用数组接收.
NSArray *eleArray = [doc.rootElement elementsForName:@"video"];
// REMARKS: GET方法异步请求cell数据
- (void)netWork
{
// 创建请求数据的url路径,XML格式的数据
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
// 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 发送GET请求,异步
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// REMARKS: 使用Google的GDataXML框架解析XML,用GDataXML框架解析XML数据,GDataXML会一次性把整个XML加载到内存,内存短时间内会增大,如果XML数据量大不推荐使用
// 一次性加载整个XML文档
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
// SINGLE: 获取XML的根元素,拿到所有名称叫做video的子元素,该例子的XML根元素为数组
NSArray *eleArray = [doc.rootElement elementsForName:@"video"];
for (GDataXMLElement *ele in eleArray) {
WXVideo *video = [[WXVideo alloc] init];
// 逐个解析每个属性元素
video.name = [ele attributeForName:@"name"].stringValue;
video.image = [ele attributeForName:@"image"].stringValue;
video.url = [ele attributeForName:@"url"].stringValue;
video.ID = [ele attributeForName:@"id"].stringValue;
video.length = [ele attributeForName:@"length"].stringValue;
// 将解析好的模型添加到数据源数组
[self.videos addObject:video];
}
// 刷新tableView数据
[self.tableView reloadData];
}];
}