ios數(shù)據(jù)解析2016

所謂"解析":從事先規(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ù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市代乃,隨后出現(xiàn)的幾起案子旬牲,更是在濱河造成了極大的恐慌,老刑警劉巖搁吓,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件原茅,死亡現(xiàn)場離奇詭異,居然都是意外死亡擎浴,警方通過查閱死者的電腦和手機(jī)员咽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門毒涧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贮预,“玉大人,你說我怎么就攤上這事契讲》峦蹋” “怎么了?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵捡偏,是天一觀的道長唤冈。 經(jīng)常有香客問我,道長银伟,這世上最難降的妖魔是什么你虹? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮彤避,結(jié)果婚禮上傅物,老公的妹妹穿的比我還像新娘。我一直安慰自己琉预,他們只是感情好董饰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般卒暂。 火紅的嫁衣襯著肌膚如雪啄栓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天也祠,我揣著相機(jī)與錄音昙楚,去河邊找鬼。 笑死齿坷,一個(gè)胖子當(dāng)著我的面吹牛桂肌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播永淌,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼崎场,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了遂蛀?” 一聲冷哼從身側(cè)響起谭跨,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎李滴,沒想到半個(gè)月后螃宙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡所坯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年谆扎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芹助。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堂湖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出状土,到底是詐尸還是另有隱情无蜂,我是刑警寧澤,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布蒙谓,位于F島的核電站斥季,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏累驮。R本人自食惡果不足惜酣倾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谤专。 院中可真熱鬧躁锡,春花似錦、人聲如沸毒租。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惕医,卻和暖如春耕漱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抬伺。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工螟够, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峡钓。 一個(gè)月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓妓笙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親能岩。 傳聞我的和親對象是個(gè)殘疾皇子寞宫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容