所謂"解析":從事先規(guī)定好的格式中提取數(shù)據(jù)
解析一共有兩種格式:JSON和XML
一、JSON
全稱JavaScript Object Notation漓糙,輕量級的數(shù)據(jù)交換格式组民。
1.數(shù)據(jù)格式:
字典:{key:value}
數(shù)組:[value1,value2]
JSON中的數(shù)據(jù)類型:字符串,數(shù)值,BOOL,對象,數(shù)組
2.示例:
字典格式1:{@"name":@"Carson"}
數(shù)組格式2:["value1","value2"]
混合格式3:[ {@"name":"Carson"}奕筐,{@"sex":"Male"}]
3.解析方法
使用系統(tǒng)推薦的方法,NSJSONSerialization
它有兩個(gè)方法钓觉,
JSON反序列化方法,也叫JSON解析坚踩,從服務(wù)器端獲得二進(jìn)制 數(shù)據(jù)荡灾,轉(zhuǎn)為OC對象就是反序列化。
JSONObjectWithData: option: error:
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSArray *array= [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSString *string= [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
服務(wù)器傳過來的二進(jìn)制數(shù)據(jù)瞬铸,可以轉(zhuǎn)為oc對象批幌,它可以是id類型,可以是字典嗓节,數(shù)組荧缘、以及字符串。
JSON序列化拦宣,把OC對象轉(zhuǎn)為二進(jìn)制數(shù)據(jù)截粗,上傳給服務(wù)器。
dataWithJSONObejct:option:error:
NSDictionary *dic1 = @{@"name":@"cj",@"age":@"27"};
NSDictionary *dic2 = @{@"name":@"cj2527",@"age":@"27"};
NSArray *array = @[dic1,dic2];
//檢測能否被序列化
if (![NSJSONSerialization isValidJSONObject:array]) {
NSLog(@"格式不正確鸵隧!");
return;
}
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:array options:0 error:NULL];
使用第三方框架
MJExtension
下載地址和詳細(xì)說明
https://github.com/CoderMJLee/MJExtension#Getting_Started
二绸罗、XML
全稱Extensible Markup language,可拓展標(biāo)記語言
它的解析方式有兩種:
SAX(Simple API for XML):事件驅(qū)動機(jī)制。從根元素開始豆瘫,按順序一個(gè)個(gè)元素往下解析珊蟀,它只在XML文檔中查找特定條件的內(nèi)容,并且只提取需要的東西外驱,占用內(nèi)存少系洛,也比較靈活俊性,所以適合解析大文件。
DOM(Document Object Model):文檔對象模型描扯。一次性將整個(gè)XML文檔加載進(jìn)內(nèi)存定页,放在一個(gè)樹型結(jié)構(gòu)中,需要的時(shí)候查找特定節(jié)點(diǎn)绽诚。實(shí)現(xiàn)簡單典徊,讀寫平衡,但是比較占內(nèi)存恩够,適合解析小文件卒落。
xml格式有兩種結(jié)構(gòu):
結(jié)構(gòu)一:
<?xml version="1.0" encoding="utf-8"?> <!--此行包含XML的版本信息和編碼格式-->
<Students className = "cj">
<Student name = "張三" age = "18"/>
<Student name = "李四" age = "18"/>
</Students>
這種結(jié)構(gòu)的解析比較容易,參考以下鏈接文章蜂桶。
http://www.reibang.com/p/2eb1c93d75bb
結(jié)構(gòu)二:
<?xml version="1.0" encoding="utf-8"?> <!--此行包含XML的版本信息和編碼格式-->
<students><!--這是開始標(biāo)簽儡毕,也就是根節(jié)點(diǎn)-->
<student attribute = "學(xué)生A" ><!--student為根節(jié)點(diǎn)的子節(jié)點(diǎn),name節(jié)點(diǎn)的父節(jié)點(diǎn)扑媚, attribute是它的屬性-->
<name>張三</name><!--張三 為name節(jié)點(diǎn)的值-->
<sex>男</sex>
<age>23</age>
</student>
<student attribute = "學(xué)生B">
<name>李四</name>
<sex>男</sex>
<age>22</age>
</student>
</students><!--節(jié)點(diǎn)的結(jié)束標(biāo)簽都是以/加標(biāo)簽名稱組成 -->
這種結(jié)構(gòu)使用系統(tǒng)原生的NSXMLParse解析腰湾,相對復(fù)雜,參考http://www.reibang.com/p/c82eaaf8b47a
//1.實(shí)例化一個(gè)xml解析疆股,通過代理實(shí)現(xiàn)XML的解析
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
//2.設(shè)置代理
parser.delegate = self;
//3.開始解析
[parser parse];
遵守代理協(xié)議费坊,實(shí)現(xiàn)代理的5個(gè)方法
parserDidStartDocument//打開文檔
parser:didStartElement //開始節(jié)點(diǎn)
parser:foundCharacters //發(fā)現(xiàn)節(jié)點(diǎn)內(nèi)容
parser:didEndElement //結(jié)束節(jié)點(diǎn)
parserDidEndDocument //結(jié)束文檔
具體實(shí)現(xiàn)如下:
//1.打開文檔,準(zhǔn)備解析,一般在這里邊用來將保存數(shù)據(jù)的數(shù)組暫時(shí)清空
-(void)parserDidStartDocument:(nonnull NSXMLParser *)parser{
// 初始化數(shù)據(jù)容器旬痹,清空數(shù)據(jù)附井,便于多次調(diào)用
[self.videos removeAllObjects];
}
//2.開始節(jié)點(diǎn),一般在這里主要進(jìn)行數(shù)據(jù)模型的初始化和讀取節(jié)點(diǎn)的屬性值
-(void)parser:(nonnull NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict{
// 創(chuàng)建對象
if ([elementName isEqualToString:@"video"]) {
self.currentVideo =[[Video alloc]init];
//設(shè)置videoID
self.currentVideo.videoId = [NSNumber numberWithInteger:[attributeDict[@"videoId"] integerValue]];
}
//在準(zhǔn)備開始解析下一個(gè)節(jié)點(diǎn)的數(shù)據(jù)時(shí),先把數(shù)據(jù)清空
//清空字符串的內(nèi)容两残,因?yàn)轳R上要進(jìn)入第三個(gè)方法永毅,要重寫拼接字符串了
[self.elementString setString:@""];
NSLog(@"開始節(jié)點(diǎn):%@,%@",elementName,attributeDict);
}
//3.發(fā)現(xiàn)節(jié)點(diǎn)內(nèi)容,解析節(jié)點(diǎn)之間的字符。 當(dāng)解析器找到開始標(biāo)記和結(jié)束標(biāo)記之間的字符時(shí)人弓,調(diào)用這個(gè)方法解析當(dāng)前節(jié)點(diǎn)內(nèi)的所有字符
-(void)parser:(nonnull NSXMLParser *)parser foundCharacters:(nonnull NSString *)string{
//開始拼接字符串, 將一個(gè)節(jié)點(diǎn)中讀取到的數(shù)據(jù)進(jìn)行拼接
[self.elementString appendString:string];
NSLog(@"發(fā)現(xiàn)節(jié)點(diǎn)內(nèi)容:%@",string);
}
//4.結(jié)束節(jié)點(diǎn),卷雕,在這個(gè)方法里通常進(jìn)行數(shù)據(jù)的保存
-(void)parser:(nonnull NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName{
//如果遇到了結(jié)束節(jié)點(diǎn)符號,則進(jìn)行數(shù)據(jù)的保存
if ([elementName isEqualToString:@"video"]) {
[self.videos addObject:self.currentVideo];
}else if(![elementName isEqualToString:@"videos"]){
//如果既不是數(shù)據(jù)的最后一個(gè)節(jié)點(diǎn),也不是根節(jié)點(diǎn)票从,即為數(shù)據(jù)中間的節(jié)點(diǎn)漫雕,則將數(shù)據(jù)對應(yīng)保存到模型中
//運(yùn)用KVC保存,效率高峰鄙,不過屬性的名字一定要和節(jié)點(diǎn)的名稱相對應(yīng)
[self.currentVideo setValue:self.elementString forKey:elementName];
}
NSLog(@"結(jié)束節(jié)點(diǎn):%@",elementName);
}
//5.結(jié)束文檔
-(void)parserDidEndDocument:(nonnull NSXMLParser *)parser{
//xml真正解析結(jié)束浸间,可以更新UI等,在主線程
dispatch_async(dispatch_get_main_queue(), ^{
// self.dataList = self.videos;//給tableView的模型數(shù)組賦值
});
NSLog(@"5:結(jié)束文檔");
}
補(bǔ)充下屬性申明
@interface ViewController () <NSXMLParserDelegate>
@property (nonatomic,strong)NSMutableArray *videos;//xml的數(shù)據(jù)容器
@property (nonatomic,strong)NSMutableString *elementString;//第三步驟拼接字符串
@property (nonatomic,strong)Video *currentVideo;//當(dāng)前模型
@property (nonatomic,strong)NSMutableArray *dataList;//存放表格的所有數(shù)據(jù)
@end
也可以用第三方框架XMLReader讀取比較方便吟榴,代碼較少魁蒜。
做點(diǎn)補(bǔ)充吧
//1. 轉(zhuǎn)化成xmlReader能轉(zhuǎn)化的類型
NSString *path = [[NSBundle mainBundle] pathForResource:@"demo.xml" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSData *data = [NSData dataWithContentsOfURL:url];
//2. 開始轉(zhuǎn)化
NSError *error;
NSDictionary *dic = [XMLReader dictionaryForXMLData:data error:&error];
NSLog(@"%@",dic);
NSArray *list = [[dic objectForKey:@"students"]objectForKey:@"student"];
// NSLog(@"%@",list);
if (![list isKindOfClass:[NSArray class]])
{
// if 'list' isn't an array, we create a new array containing our object
list = [NSArray arrayWithObject:list];
}
//
// // we can loop through items safely now
NSMutableArray *nameArr = [NSMutableArray array];
for (NSDictionary *item in list)
{
Model *model = [[Model alloc]init];
[model setValuesForKeysWithDictionary:item];
[nameArr addObject: model];
}
//獲得模型數(shù)據(jù),就可以更新UI了
//NSLog(@"%@",nameArr);
//獲取第一個(gè)學(xué)生的信息
Model *model2 = nameArr[0];
NSLog(@"屬性:%@,name=%@,sex=%@,age=%@",model2.attribute ,model2.name,model2.sex,model2.age);
運(yùn)用kvc方法,得注意key保持一致
model模型如下:
@interface Model : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *attribute;
@property (nonatomic, copy) NSString *text;//xmlReader必須要的
@property (nonatomic, copy) NSString *sex;
@property (nonatomic, copy) NSString *age;
@end
JSON和XML的對比
JSON的優(yōu)點(diǎn):格式簡單兜看,占用帶寬小锥咸,易于讀寫,易于解析细移,易于維護(hù)搏予,支持多語言
缺點(diǎn):沒有xml廣泛,沒有xml那樣通用性
XML的優(yōu)點(diǎn):格式統(tǒng)一弧轧、符合標(biāo)準(zhǔn)雪侥,易于和其他系統(tǒng)進(jìn)行遠(yuǎn)程交互,方便數(shù)據(jù)共享
缺點(diǎn):文件龐大精绎、占用帶寬大速缨、服務(wù)器端和客戶端需要大量代碼來解析xml,不易于維護(hù)