【iOS开发】JSON和XML数据解析

在iOS开发中,只要是涉及到网络的应用,几乎都离不开JSON或者XML。但是目前比较常见的是JSON数据格式。

JSON解析

JSON解析的第三方库有很多,我们这里只讲一种第三方库JSONKit和官方的解析方法。

JSONKit

首先把JSON格式的数据转换成String,然后再调用JSONKit定义的jsonStr.objectFromJSONString方法,就可以转换成一个字典,方便我们使用。(JSONKit请自己下载)

@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

其实官方的解析方法也非常简单,调用URLSessiondataTask(with: completionHandler:)方法,然后在completionHandler回调里面就能得到我们想要的数据。如果error不为空或者datanil,意味着解析错误或者服务器没有数据,那么用return返回。回调里面实在子线程中执行的,所以要回到主线程中更新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 { // 在主线程中更新UI
                    self.show(text: "请求失败")
                }
                return
            }
            
            if let dict = try? JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as? Dictionary<String, Any> {
                print(dict! as Any)
                
                DispatchQueue.main.sync { // 在主线程中更新UI
                    self.show(text: "解析成功")
                }
            }
        })
        
        task.resume()
    }
}

XML解析

XML的解析方式有两种:1)DOM:一次性将整个文档加载进内存,比较适合解析小文件,其中一个常用的第三方框架是GDataXML;2)SAX:从根元素开始,按顺序一个个元素往下解析,比较适合大文件,苹果自带的XMLParser就属于这个类型。

XMLParser

XMLParser是通过代理的方式实现的,它一边解析,一边通知代理。

@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() // 开始解析
    }
}

// MARK: - XMLParserDelegate
extension ViewController: XMLParserDelegate {
    
    // 解析到文档开头调用
    func parserDidStartDocument(_ parser: XMLParser) {
        print("parserDidStartDocument")
    }
    
    // 解析到一个元素的开始就会调用
    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-------")
    }
    
    // 解析到节点时调用
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        print("-------foundCharacters-------")
        print(string)
        print("-------foundCharacters-------")
    }
    
    // 解析到一个元素的结尾就会调用
    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-------")
    }
    
    // 解析到文档结尾调用
    func parserDidEndDocument(_ parser: XMLParser) {
        print("parserDidEndDocument")
    }
}
GDataXML

我们把GDataXML.m.h拖到项目中后,需要做一下配置:

  • 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

解析过程如下:

    @IBAction func extractXMLWithGDataXML() {
        let path = Bundle.main.path(forResource: "info.xml", ofType: nil)!
        if let data = try? NSData(contentsOfFile: path) as Data {
            // 加载整个XML
            if let doc = try? GDataXMLDocument(data: data, options: 0) {
                // 获取根节点
                let rootDoc = doc.rootElement()!
                // 获取所有city节点
                if let cities = rootDoc.elements(forName: "city") as? [GDataXMLElement] {
                    for city in cities {
                        // 获取name节点
                        let name = city.elements(forName: "name").first as! GDataXMLElement
                        print(name.stringValue())
                    }
                }
            }
        }
    }

Demo地址 >>

如果文中有错误,请指出!我们共同学习,共同进步。谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容