JSON与XML数据解析
- JSON数据解析(内置NSJSONSerialization与第三方JSONKit)
一,使用自带的NSJSONSerialization
苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其他第三方开源项目高。
NSJSONSerialization能将JSON转换成Foundation对象,也能将Foundation对象转换成JSON,但转换成JSON的对象必须具有如下属性:
- 1,顶层对象必须是NSArray或者NSDictionary
- 2,所有的对象必须是NSString、NSNumber、NSArray、NSDictionary、NSNull的实例
- 3,所有NSDictionary的key必须是NSString类型
- 4,数字对象不能是非数值或无穷
- 注意:尽量使用NSJSONSerialization.isValidJSONObject先判断能否转换成功。
样例如下:
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. var label:UILabel = UILabel(frame:CGRectMake(, ,,)); label.text = "输出结果在控制台" self.view.addSubview(label) //测试结果在output终端输入,也可以建个命令行应用测试就可以了 testJson() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //测试json func testJson() { //Swift对象 let user = [ "uname": "张三", "] ] //首先判断能不能转换 if (!NSJSONSerialization.isValidJSONObject(user)) { println("is not a valid json object") return } //利用OC的json库转换成OC的NSData, //如果设置options为NSJSONWritingOptions.PrettyPrinted,则打印格式更好阅读 let data : NSData! = NSJSONSerialization.dataWithJSONObject(user, options: nil, error: nil) //NSData转换成NSString打印输出 let str = NSString(data:data, encoding: NSUTF8StringEncoding) //输出json字符串 println("Json Str:"); println(str) //把NSData对象转换回JSON对象 let json : AnyObject! = NSJSONSerialization .JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error:nil) println("Json Object:"); println(json) //验证JSON对象可用性 let uname : AnyObject = json.objectForKey("uname")! let mobile : AnyObject = json.objectForKey("tel")!.objectForKey("mobile")! println("get Json Object:"); println("uname: \(uname), mobile: \(mobile)") } }
输出结果如下:
Json Str: Optional({"}}) Json Object: { tel = { home = ; mobile = ; }; uname = "\U5f20\U4e09"; } get Json Object: uname: 张三, mobile:
二,使用第三方库 - JSONKit
#include "JSONKit.h"
1,新建桥街头文件Bridging-Header.h,并设置到编译参数里
2,将JSONKit的库文件导入到项目中来(JSONKit.h和JSONKit.m)
3,这时编译会发现报错,这是由于JSONKit库不支持Objective-C的自动引用计数功能导致。
需要在Build Phases -> Compile Sources -> JSONKit.m,双击添加Comipler Flag:-fno-objc-arc 。这样就完成了不支持自动引用计数的配置。
测试代码:
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. testJson() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func testJson() { //Swift 字典对象 let user = [ "uname": "user1", "] ] //使用 JSONKit 转换成为 JSON 字符串 var jsonstring = (user as NSDictionary).JSONString() println(jsonstring); //由字符串反解析回字典 println(jsonstring.objectFromJSONString() as NSDictionary) //使用 JSONKit 转换成为 NSData 类型的 JSON 数据 var jsondata = (user as NSDictionary).JSONData() println(jsondata); //由NSData 反解析回为字典 println(jsondata.objectFromJSONData() as NSDictionary) } }
输出结果:
{"}} { tel = { home = ; mobile = ; }; uname = user1; } <7b22756e 616d6522 3a227573 2c227465 6c223a7b 22686f6d 65223a22 2c226d6f 62696c65 223a2231 3338227d 7d> { tel = { home = ; mobile = ; }; uname = user1; }
目前实际开发中使用比较多的是第三方框架来解析的,后面会介绍一个比较好用,而且是大多数程序员比较喜欢的JSON解析框架:SwiftyJSON
解析XML格式数据(分别使用GDataXML和DDXML)
在做一些应用的时候经常需要用到XML解析,比如获取Web Service数据,读取RSS新闻或者博客数据源。下面演示了两个非常方便高效的XML库在Swift里的调用方法。
假设需要被解析的XML数据文件users.xml如下:
<?xml version="1.0" encoding="utf-8"?> <Users> <User "> <name>航歌</name> <tel> <mobile></mobile> <home>-</home> </tel> </User> <User "> <name>hangge</name> <tel> <mobile></mobile> <home>-</home> </tel> </User> </Users>
我们需要实现的功能是解析并打印出需要的数据:
User: uid:,uname:航歌,mobile:,home:- User: uid:,uname:hangge,mobile:,home:-
一,使用GDataXML(这个是google出品的)
1,在build phases -> Link Binary With Libraries中,点击“+”添加“libxml2.2.dylib”
2,在build setting -> Header Search Paths里添加 ${SDK_DIR}/usr/include/libxml2
3,在build setting里的Objective-C编译选项里,把自动引用计数改为No,否则在应用GDataXML库时会编译有错
4,添加bridge.h头文件并设置到编译参数里
#import "GDataXMLNode.h"
5,导入GDataXML库文件(GDataXMLNode.h和GDataXMLNode.m),代码结构如下:
6,开始解析(ViewController.swift)
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. var label:UILabel = UILabel(frame:CGRectMake(, ,,)); label.text = "输出结果在控制台" self.view.addSubview(label) //测试Swift调用Object的XML库功能 testXML() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func testXML() { //获取xml文件路径 var path = NSBundle.mainBundle().pathForResource("users", ofType:"xml") //获取xml文件内容 var xmlData = NSData(contentsOfFile:path!) //可以转换为字符串输出查看 //println(NSString(data:xmlData, encoding:NSUTF8StringEncoding)) //使用NSData对象初始化文档对象 //这里的语法已经把OC的初始化函数直接转换过来了 var doc:GDataXMLDocument = GDataXMLDocument(data:xmlData, options : , error : nil) //获取Users节点下的所有User节点,显式转换为element类型编译器就不会警告了 //var users = doc.rootElement().elementsForName("User") as GDataXMLElement[] //通过XPath方式获取Users节点下的所有User节点,在路径复杂时特别方便 var users = doc.nodesForXPath("//User", error:nil) as [GDataXMLElement] for user in users { //User节点的id属性 let uid = user.attributeForName("id").stringValue() //获取name节点元素 let nameElement = user.elementsForName(] as GDataXMLElement //获取元素的值 let uname = nameElement.stringValue() //获取tel子节点 let telElement = user.elementsForName(] as GDataXMLElement //获取tel节点下mobile和home节点 let mobile = (telElement.elementsForName(] as GDataXMLElement).stringValue() let home = (telElement.elementsForName(] as GDataXMLElement).stringValue() //输出调试信息 println("User: uid:\(uid),uname:\(uname),mobile:\(mobile),home:\(home)") } } }
二,使用DDXML
1,2,3步同上
4,添加bridge.h头文件并设置到编译参数里
#import "DDXMLElementAdditions.h"
5,导入DDXML库文件
6,开始解析(ViewController.swift)
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. var label:UILabel = UILabel(frame:CGRectMake(, ,,)); label.text = "输出结果在控制台" self.view.addSubview(label) //测试Swift调用Object的XML库功能 testXML() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func testXML() { //获取xml文件路径 var path = NSBundle.mainBundle().pathForResource("users", ofType:"xml") //获取xml文件内容 var xmlData = NSData(contentsOfFile:path!) //构造XML文档 var doc = DDXMLDocument(data: xmlData, options:, error:nil) //利用XPath来定位节点(XPath是XML语言中的定位语法,类似于数据库中的SQL功能) var users = doc.nodesForXPath("//User", error:nil) as [DDXMLElement] for user in users { let uid = user.attributeForName("id").stringValue() //DDXMLElementAdditions提供了elementForName获取单个节点,不用获取数组了 let uname = user.elementForName("name").stringValue() //获取tel节点的子节点 let telElement = user.elementForName("tel") as DDXMLElement let mobile = (telElement.elementForName("mobile") as DDXMLElement).stringValue() let home = (telElement.elementForName("home") as DDXMLElement).stringValue() println("User: uid:\(uid),uname:\(uname),mobile:\(mobile),home:\(home)") } } }