【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
            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 {
                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地址 >>

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

你可能感兴趣的:(【iOS开发】JSON和XML数据解析)