国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

iOS-JSon和Xml解析,與服務(wù)器交互數(shù)據(jù)的解析詳解與使用,各種解析方式詳解

2019-11-14 18:32:48
字體:
供稿:網(wǎng)友

JSon和xml解析,與服務(wù)器交互必許學(xué)會

什么是JSon?什么是Xml?

在移動應(yīng)用開發(fā)中,客戶端經(jīng)常要與服務(wù)器進(jìn)行交互,獲得服務(wù)器的數(shù)據(jù),進(jìn)行展示。那么獲取的數(shù)據(jù)的格式,就是JSon或者Xml格式(大多數(shù)),而現(xiàn)在,因?yàn)镴Son格式的輕量級,和方便使用的特性,在市場占有中已經(jīng)90%左右。

我們先學(xué)習(xí)一下JSon格式的數(shù)據(jù)

我們來看看JSon格式的數(shù)據(jù)長什么樣子:

```
{

   "access_token": "ACCESS_TOKEN",   "expires_in": 1234,   "remind_in":"798114",   "uid":"12341234"

}
```
這是一段新浪微博返回的JSon格式數(shù)據(jù),是不是覺得樣子長得很像OC中的字典,對,沒錯(cuò),在iOS開發(fā)中我們也是要將這種數(shù)據(jù)轉(zhuǎn)化成OC的數(shù)據(jù)類型,方便我們使用。

在上面的數(shù)據(jù)中,我們注意到:JSon數(shù)據(jù)的key都有“”包裹,這說明你觀察的挺仔細(xì)的。這也是JSon數(shù)據(jù)的格式要求,那么,JSon數(shù)據(jù)怎么轉(zhuǎn)換成OC的數(shù)據(jù)類型呢???我們先看看他們之間的聯(lián)系吧。

你要是還不清楚這張圖在說什么,就看看下面的對應(yīng)關(guān)系:

JSON數(shù)據(jù)(NSData) -> OC對象(Foundation Object)

  • {} -> NSDictionary @{}
  • [] -> NSArray @[]
  • "jack" -> NSString @"jack"
  • 10 -> NSNumber @10
  • 10.5 -> NSNumber @10.5
  • true -> NSNumber @1
  • false -> NSNumber @0
  • null -> NSNull

這下肯定知道什么意思了吧。

有了這個(gè)一一對應(yīng)的關(guān)系,我們就能方便的進(jìn)行轉(zhuǎn)換了。
JSon解析方法
---
性能最好的解析方法是:蘋果原生(自帶):NSJSONSerialization

也有第三方框架:JSONKit、SBJson、TouchJSON(性能從左到右,越來越差)

但是我們并不會都學(xué),因?yàn)閷W(xué)那么多也不會都用得上,so...開始吧


我們來學(xué)習(xí)一下性能最好的解析方式:
NSJSONSerialization

常使用的方法是:


將JSON數(shù)據(jù) -> 轉(zhuǎn)換成OC對象

+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;

參數(shù)options詳解:

- NSJSONReadingOptions    - NSJSONReadingMutableContainers = (1UL << 0)        - 創(chuàng)建出來的數(shù)組和字典就是可變    - NSJSONReadingMutableLeaves = (1UL << 1)        - 數(shù)組或者字典里面的字符串是可變的    - NSJSONReadingAllowFragments        - 允許解析出來的對象不是字典或者數(shù)組,比如直接是字符串或者NSNumber

這樣干講是不是覺得學(xué)的不牢固,那么我們來試試?yán)訉W(xué)習(xí)吧:

例子

//請求服務(wù)器的數(shù)據(jù)    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {        //查看原數(shù)據(jù)的類型        NSLog(@"原數(shù)據(jù)%@",data);        //對數(shù)據(jù)用NSJSONSerialization解析成OC數(shù)據(jù)類型        NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];        NSLog(@"轉(zhuǎn)換后的數(shù)據(jù)%@",dict);    }];

上面的例子你可以實(shí)現(xiàn)將服務(wù)器返回的數(shù)據(jù)轉(zhuǎn)換成OC的數(shù)據(jù)


將OC對象 -> 轉(zhuǎn)換成JSON數(shù)據(jù)

函數(shù)原型

+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

參數(shù):NSJSONWritingPRettyPrinted 表示: 對轉(zhuǎn)換之后的JSON進(jìn)行排版

舉例論證

//創(chuàng)建字典    NSDictionary *dict = @{                            @"name": @"xueyinliang",                            @"car":@"baoma",                            @"id":@1                           };    NSLog(@"%@",dict);    //將字典轉(zhuǎn)換成JSon數(shù)據(jù)    NSData *data =[NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];    NSLog(@"%@",data);

打印結(jié)果:

2015-08-11 15:32:46.890 JSonAndOC[4767:149687] {    car = baoma;    id = 1;    name = xueyinliang;}2015-08-11 15:32:46.894 JSonAndOC[4767:149687] <7b0a2020 226e616d 6522203a 20227875 6579696e 6c69616e 67222c0a 20202263 61722220 3a202262 616f6d61 222c0a20 20226964 22203a20 310a7d>

這樣,我們就輕松學(xué)會了JSon和OC數(shù)據(jù)類型的轉(zhuǎn)換了。


xml數(shù)據(jù)的解析

雖然,JSon數(shù)據(jù)的市場應(yīng)用占有率很大,但是我們還是要學(xué)習(xí)一下XML數(shù)據(jù)的解析。因?yàn)檫@種格式的數(shù)據(jù)還是有一些公司會用到的。

xml數(shù)據(jù)長什么樣子?

xml數(shù)據(jù)是一種可擴(kuò)展的標(biāo)記語言,因?yàn)樗拿恳粋€(gè)元素都是由特定的標(biāo)記擴(kuò)起來的。

例如:
每一個(gè)元素都有一個(gè)開始和結(jié)束標(biāo)簽

<video>元素名</video>

元素可以嵌套子元素

<video>    <name>世界你好</name>    <length>30</length></video>

所有元素前面要有聲明

<?xml version="1.0" encoding="UTF-8" ?>

注意:這里的所有空格和換行,也是數(shù)據(jù)的一部分,會被處理。這也是為什么xml數(shù)據(jù)容量大的原因。

下面,我們來學(xué)習(xí)一下怎么解析xml數(shù)據(jù),這才是重點(diǎn)。

XML數(shù)據(jù)的解析方式

  • XML的解析方式有2種

    • DOM:一次性將整個(gè)XML文檔加載進(jìn)內(nèi)存,比較適合解析小文件
    • SAX:從根元素開始,按順序一個(gè)元素一個(gè)元素往下解析,比較適合解析大文件

####然而,我們怎么選擇和怎么使用這兩種解析方式呢?

下面將給出選擇方案:(基于兩種方式的特點(diǎn)選擇)

  • XML解析方式的選擇建議

    • 大文件:NSXMLParser、libxml2
    • 小文件:GDataXML、NSXMLParser、libxml2

我們必須知道上面的這幾種方法各有什么特點(diǎn),才會使用:

蘋果原生

NSXMLParser:SAX方式解析,使用簡單

第三方框架

libxml2:純C語言,默認(rèn)包含在iOS SDK中,同時(shí)支持DOM和SAX方式解析GDataXML:DOM方式解析,由Google開發(fā),基于libxml2

雖然libxml2可以同時(shí)支持dom和sax方式的解析,但是因?yàn)槠涫褂寐闊栽趯?shí)際開發(fā)中,并不常用,而是SAX方式解析大文件的時(shí)候使用NSXMLParser,DOM方式解析小文件的時(shí)候使用GDataXML或NSXMLParser。


XML解析的方式介紹過了,我們再來看看到底怎么使用他們吧。

首先是如何使用NSXMLParser

使用NSXMLParser解析數(shù)據(jù)很簡單,你只需要傳遞過來XML數(shù)據(jù),然后在NSXMLParser的代理方法里面解析就好了。這時(shí)候NSXMLParser的代理方法會當(dāng)讀到XML文件的開頭和結(jié)尾,以及讀到元素標(biāo)簽的開始和結(jié)尾的時(shí)候通知代理,并調(diào)用相應(yīng)的代理方法來執(zhí)行。為了防止有朋友不清楚哪里是XML文件的開頭和結(jié)尾,哪里是元素的開頭和結(jié)尾,這里給出一張圖來明確表示一下:

下面給出代碼如何開始和如何設(shè)置代理方法:

// 傳入XML數(shù)據(jù),創(chuàng)建解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 設(shè)置代理,監(jiān)聽解析過程parser.delegate = self;// 開始解析[parser parse];

代理方法

當(dāng)掃描到文檔的開始時(shí)調(diào)用(開始解析)- (void)parserDidStartDocument:(NSXMLParser *)parser當(dāng)掃描到文檔的結(jié)束時(shí)調(diào)用(解析完畢)- (void)parserDidEndDocument:(NSXMLParser *)parser當(dāng)掃描到元素的開始時(shí)調(diào)用(attributeDict存放著元素的屬性)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict當(dāng)掃描到元素的結(jié)束時(shí)調(diào)用- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName/** *  解析發(fā)生錯(cuò)誤時(shí)調(diào)用 */- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError;

舉例

在獲取到網(wǎng)絡(luò)數(shù)據(jù)以后:

// 1.創(chuàng)建XML解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 2.成為NSXMLParser的代理parser.delegate = self;// 3.開始解析XML[parser parse];

然后在代理方法中拿到數(shù)據(jù):

/** *  開始解析XML文檔中的每一個(gè)元素時(shí)調(diào)用 */- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{    // 2.videos    // 3.video    // 5.video    if ([elementName isEqualToString:@"videos"]) {        return;    }        XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict];//使用MJExtension轉(zhuǎn)換模型    [self.videos addObject:video];}

然后就可以拿到數(shù)據(jù)數(shù)組,進(jìn)行各種顯示的操作了


接下來我們看看GDATAXML怎么使用

1,GDataXML基于libxml2庫,得做以下配置

  • 導(dǎo)入libxml2庫

  • 設(shè)置libxml2的頭文件搜索路徑(為了能找到libxml2庫的所有頭文件)
    在Head Search Path中加入/usr/include/libxml2

  • 設(shè)置鏈接參數(shù)(自動鏈接libxml2庫)
    在Other Linker Flags中加入-lxml2

  • 由于GDataXML是非ARC的,因此得設(shè)置編譯參數(shù)

GDataXML中常用的類

  • GDataXMLDocument:代表整個(gè)XML文檔

  • GDataXMLElement
    代表文檔中的每個(gè)元素

  • 使用attributeForName:方法可以獲得屬性值

舉例

在獲取到網(wǎng)絡(luò)數(shù)據(jù)以后:

 // 1.加載所有的xml到內(nèi)存中        GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];        // 2.獲取根元素        GDataXMLElement *rootElement = doc.rootElement;        // 3.從根元素中獲取所有子元素        NSArray *elements = [rootElement elementsForName:@"video"];        // 4.將子元素中的屬性轉(zhuǎn)換為模型        for (GDataXMLElement *ele in elements) {            XMGVideo *video = [[XMGVideo alloc] init];            video.image = [ele attributeForName:@"image"].stringValue;            video.url = [ele attributeForName:@"url"].stringValue;            video.name = [ele attributeForName:@"name"].stringValue;            video.length = @([ele attributeForName:@"length"].stringValue.integerValue);            [self.dataArray addObject:video];            //dataArray是數(shù)據(jù)的數(shù)組        }

然后就可以拿到數(shù)據(jù)數(shù)組,進(jìn)行各種顯示的操作了

如果還有哪里不懂的,


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 德州市| 大同县| 伊川县| 凌云县| 宿松县| 洞头县| 巴林右旗| 邵武市| 剑河县| 梨树县| 雷州市| 河间市| 洮南市| 海阳市| 大悟县| 旅游| 海原县| 洱源县| 榆中县| 枝江市| 泗水县| 山阴县| 绵竹市| 即墨市| 荔波县| 临潭县| 伊宁县| 弥勒县| 安国市| 通山县| 鹰潭市| 长岛县| 项城市| 沅江市| 柞水县| 陈巴尔虎旗| 土默特左旗| 日土县| 黄冈市| 固原市| 民县|