iOS開發過程中,網絡數據的傳輸過程一般是:客戶端發送請求給服務器,服務器接收到客戶端發送的網絡請求后返回相應的數據。此時客戶端需要把服務器返回的數據轉化為前段和移動端開發中使用的數據格式(如OC/java)。后台服務器一般使用php、java、.net進行開發,而前段和移動端使用的一般是OC/JAVA/HTML/CSS/JS,做好前后端的數據交互極為重要,如今數據交互常用的就是JSON和XML。下面就iOS開發過程中的JSON解析和XML解析進行簡單的說明。
一、JSON解析
JSON是一種輕量級的數據格式,一般用於數據交互。JSON是javascript語言的一個子集.javascript是個腳本語言(不需要編譯),用來給HTML增加動態功能(此處的 javascript和java沒有半毛錢的關系!)
在iOS中,常見的JSON數據解析方案有4種:
第三方框架: SBJson ,JSONKit, TouchJson.性能從左到右,依次變差.(iOS 5(2011年)以前)
蘋果原生(自帶):NSJSONSerialization (性能是最好的.iOS5以后推出).
蘋果原生的JSON解析工具封裝的效果很好,用起來也很方便,下面簡要的介紹一下JSON的解析方法。
<1>反序列化(解析):
將從服務器接收到的JSON數據(二進制數據)轉換成OC數據類型(NSArray,NSDictionary等.)的過程.
目的: JSON數據 --> OC對象; 得到數據字典或者數據數組
好處: 簡化程序的開發,方便后續的字典轉模型.
方法:
+(id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
<2>序列化:
將數組或者字典發送給服務器之前,轉換成二進制數據.
目的:OC對象 --> JSON數據;得到二進制JSON數據 NSData.
好處:方便網絡傳輸,提高傳輸速度.
方法:
+(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
此時需要注意在做序列化之前,一定使用 isValidJSONObject 檢測一下要序列化的對象,是否能夠正確被序列化
還有就是如果后台返回的json數據有誤,比如兩側的{}或者[]沒有加上,我們要通過代碼實現,下面列出實現思路,就不上代碼了。
具體思路: 1.發送網絡請求 2.用字符串接收JSON數據 3.將JSON格式標准化 4.將標准化之后的JSON字符串轉換成二進制數據 5.將標准的JSON二進制數據轉化為OC數據
二、解析XML數據
XML 全稱是Extensible Markup Language,譯作“可擴展標記語言
XML特征:
1、 XML是一種標記語言,很類似HTML
2、XML的設計宗旨是傳輸數據,而非顯示數據
3、XML標簽沒有被預定義。您需要自行定義標簽。
4、XML被設計為具有自我描述性。
5、XML是W3C的推薦標准
XML是獨立於軟件和硬件的信息傳輸工具。 目前,XML在Web中起到的作用不會亞於一直作為 Web 基石的 HTML。 XML無所不在。XML是各種應用程序之間進行數據傳輸的最常用的工具,並且在信息存儲和描述領域變得越來越流行。
XML解析三種方式
DOM
通用性強,它會將XML文件的所有內容讀取到內存中,然后允許您使用DOM API遍歷XML樹、檢索所需的數據;
簡單直觀,但需要將文檔讀取到內存,並不太適合移動設備;
SAX、PULL解析
SAX采用事件驅動,它並不需要解析整個文檔;PULL(用於java解析),是Android自帶的XML解析器,和SAX基本類似,也是事件驅動,不同的是PULL事件返回的是數值型。
他們的區別為:SAX解析器的工作方式是自動將事件推入注冊的事件處理器進行處理,因此你不能控制事件的處理主動結束;而Pull解析器的工作方式為允許你的應用程序代碼主動從解析器中獲取事件,正因為是主動獲取事件,因此可以在滿足了需要的條件后不再獲取事件,結束解析。這是他們主要的區別。如果在一個XML文檔中我們只需要前面一部分數據,但是使用SAX方式或DOM方式會對整個文檔進行解析,中間不能終止暫停,盡管XML文檔中后面的大部分數據我們其實都不需要解析,因此這樣實際上就浪費了處理資源。使用PULL方式正合適。
下面就iOS開發中的XML解析舉個例子:
//NSXMLParserDelegate // 1. 實例化 XML 的 SAX 解析器! NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; // 2. 設置解析器代理. delegate = self; // 3. 開始解析 XML 文檔 // 一旦調用了下面的開始解析方法,就會自動調用代理方法,解析 XML 文檔! [parser parse]; #pragma NSXMLParserDelegate - (void)parserDidStartDocument:(NSXMLParser *)parser { NSLog(@"1.XML文檔解析開始!"); } // 開始解析元素的時候就會調用!XML文檔中有多少個元素就會調用多個次! // elementName:元素名稱! // attributeDict:屬性字典!當前元素對應的屬性字典! - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(NSDictionary<NSString *, NSString *> *)attributeDict { NSLog(@"2.開始解析:%@元素,元素屬性是:%@",elementName,attributeDict); // 判斷:只有元素 vedio 的屬性字典是需要的內容! if ([elementName isEqualToString:@"vedio"]) { // 字典轉模型 CZVideo *video = [CZVideo videoWithDict:attributeDict]; // 添加到數據源中 [self.videos addObject:video]; } } // 發現元素內容的時候就會調用! // string :元素內容! - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"3.發現元素內容:%@",string); } // 元素解析結束的時候就會調用,XML文檔中有多少個元素就會調用多個次! // elementName :元素名稱 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName { NSLog(@"4.元素%@解析結束",elementName); } - (void)parserDidEndDocument:(NSXMLParser *)parser { NSLog(@"5.XML文檔解析結束!"); }