【iOS開(kāi)發(fā)】JSON和XML數(shù)據(jù)解析

在iOS開(kāi)發(fā)中,只要是涉及到網(wǎng)絡(luò)的應(yīng)用,幾乎都離不開(kāi)JSON或者XML肛著。但是目前比較常見(jiàn)的是JSON數(shù)據(jù)格式。

JSON解析

JSON解析的第三方庫(kù)有很多跺讯,我們這里只講一種第三方庫(kù)JSONKit和官方的解析方法策泣。

JSONKit

首先把JSON格式的數(shù)據(jù)轉(zhuǎn)換成String,然后再調(diào)用JSONKit定義的jsonStr.objectFromJSONString方法抬吟,就可以轉(zhuǎn)換成一個(gè)字典萨咕,方便我們使用。(JSONKit請(qǐng)自己下載)

@IBAction func extractJSONWithJSONKit() {
    if let url = URL(string: urlStr) {
        if let jsonStr = try? String(contentsOf: url) as NSString {
            let dict = jsonStr.objectFromJSONString() as! Dictionary<String, Any>
            print(dict)
            show(text: "解析成功")
        }
    }
    else {
        show(text: "解析失敗")
    }
    
}
JSONSerialization

其實(shí)官方的解析方法也非常簡(jiǎn)單火本,調(diào)用URLSessiondataTask(with: completionHandler:)方法危队,然后在completionHandler回調(diào)里面就能得到我們想要的數(shù)據(jù)。如果error不為空或者datanil钙畔,意味著解析錯(cuò)誤或者服務(wù)器沒(méi)有數(shù)據(jù)茫陆,那么用return返回∏嫖觯回調(diào)里面實(shí)在子線(xiàn)程中執(zhí)行的簿盅,所以要回到主線(xiàn)程中更新UI。

@IBAction func extractJSONWithJSONSerialization() {
    if let url = URL(string: urlStr) {
        let reqeust = URLRequest(url: url)
        
        let task = URLSession.shared.dataTask(with: reqeust, completionHandler: { (data, response, error) in
            if error != nil || data == nil {
                DispatchQueue.main.sync { // 在主線(xiàn)程中更新UI
                    self.show(text: "請(qǐng)求失敗")
                }
                return
            }
            
            if let dict = try? JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as? Dictionary<String, Any> {
                print(dict! as Any)
                
                DispatchQueue.main.sync { // 在主線(xiàn)程中更新UI
                    self.show(text: "解析成功")
                }
            }
        })
        
        task.resume()
    }
}

XML解析

XML的解析方式有兩種:1)DOM:一次性將整個(gè)文檔加載進(jìn)內(nèi)存揍魂,比較適合解析小文件桨醋,其中一個(gè)常用的第三方框架是GDataXML;2)SAX:從根元素開(kāi)始现斋,按順序一個(gè)個(gè)元素往下解析喜最,比較適合大文件,蘋(píng)果自帶的XMLParser就屬于這個(gè)類(lèi)型庄蹋。

XMLParser

XMLParser是通過(guò)代理的方式實(shí)現(xiàn)的瞬内,它一邊解析迷雪,一邊通知代理。

@IBAction func extractXMLWithXMLParser() {
    let path = Bundle.main.path(forResource: "info.xml", ofType: nil)!
    if let data = try? NSData.init(contentsOfFile: path) as Data {
        parser = XMLParser(data: data)
        parser.delegate = self
        parser.parse() // 開(kāi)始解析
    }
}

// MARK: - XMLParserDelegate
extension ViewController: XMLParserDelegate {
    
    // 解析到文檔開(kāi)頭調(diào)用
    func parserDidStartDocument(_ parser: XMLParser) {
        print("parserDidStartDocument")
    }
    
    // 解析到一個(gè)元素的開(kāi)始就會(huì)調(diào)用
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        print("-------didStartElement-------")
        print(elementName)
        print(namespaceURI as Any)
        print(attributeDict)
        print("-------didStartElement-------")
    }
    
    // 解析到節(jié)點(diǎn)時(shí)調(diào)用
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        print("-------foundCharacters-------")
        print(string)
        print("-------foundCharacters-------")
    }
    
    // 解析到一個(gè)元素的結(jié)尾就會(huì)調(diào)用
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        print("-------didEndElement-------")
        print(elementName)
        print(namespaceURI as Any)
        print(qName as Any)
        print("-------didEndElement-------")
    }
    
    // 解析到文檔結(jié)尾調(diào)用
    func parserDidEndDocument(_ parser: XMLParser) {
        print("parserDidEndDocument")
    }
}
GDataXML

我們把GDataXML.m.h拖到項(xiàng)目中后虫蝶,需要做一下配置:

  • Target -> Build Phases -> Link Binary With Libraries添加libxml2.2.tbd
  • Build Settings -> Header Search Paths添加/usr/include/libxml2
  • Build Settings -> Other Linker Flags添加-lxml2
  • 如果GDataXML是MRC版本章咧,不支持ARC,需要在Build Phases -> Compile Sources找到GDataXMLNode.m能真,在后面的Compiler Flags加上-fno-objc-arc

解析過(guò)程如下:

    @IBAction func extractXMLWithGDataXML() {
        let path = Bundle.main.path(forResource: "info.xml", ofType: nil)!
        if let data = try? NSData(contentsOfFile: path) as Data {
            // 加載整個(gè)XML
            if let doc = try? GDataXMLDocument(data: data, options: 0) {
                // 獲取根節(jié)點(diǎn)
                let rootDoc = doc.rootElement()!
                // 獲取所有city節(jié)點(diǎn)
                if let cities = rootDoc.elements(forName: "city") as? [GDataXMLElement] {
                    for city in cities {
                        // 獲取name節(jié)點(diǎn)
                        let name = city.elements(forName: "name").first as! GDataXMLElement
                        print(name.stringValue())
                    }
                }
            }
        }
    }

Demo地址 >>

如果文中有錯(cuò)誤赁严,請(qǐng)指出!我們共同學(xué)習(xí)舟陆,共同進(jìn)步误澳。謝謝耻矮!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秦躯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子裆装,更是在濱河造成了極大的恐慌踱承,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哨免,死亡現(xiàn)場(chǎng)離奇詭異茎活,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)琢唾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)载荔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人采桃,你說(shuō)我怎么就攤上這事懒熙。” “怎么了普办?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵工扎,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衔蹲,道長(zhǎng)肢娘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任舆驶,我火速辦了婚禮橱健,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沙廉。我一直安慰自己畴博,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布蓝仲。 她就那樣靜靜地躺著俱病,像睡著了一般官疲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亮隙,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天途凫,我揣著相機(jī)與錄音,去河邊找鬼溢吻。 笑死维费,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的促王。 我是一名探鬼主播犀盟,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蝇狼!你這毒婦竟也來(lái)了阅畴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迅耘,失蹤者是張志新(化名)和其女友劉穎贱枣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體颤专,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纽哥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栖秕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片春塌。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖簇捍,靈堂內(nèi)的尸體忽然破棺而出只壳,到底是詐尸還是另有隱情,我是刑警寧澤垦写,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布吕世,位于F島的核電站,受9級(jí)特大地震影響梯投,放射性物質(zhì)發(fā)生泄漏命辖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一分蓖、第九天 我趴在偏房一處隱蔽的房頂上張望尔艇。 院中可真熱鬧,春花似錦么鹤、人聲如沸终娃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棠耕。三九已至余佛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窍荧,已是汗流浹背辉巡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蕊退,地道東北人郊楣。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瓤荔,于是被迫代替她去往敵國(guó)和親净蚤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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