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先判断能否转换成功。
样例如下:
1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading the view, typically from a nib. 8 var label:UILabel = UILabel(frame:CGRectMake(100, 100,300,100)); 9 label.text = "输出结果在控制台" 10 self.view.addSubview(label) 11 //测试结果在output终端输入,也可以建个命令行应用测试就可以了 12 testJson() 13 } 14 15 override func didReceiveMemoryWarning() { 16 super.didReceiveMemoryWarning() 17 // Dispose of any resources that can be recreated. 18 } 19 20 //测试json 21 func testJson() { 22 //Swift对象 23 let user = [ 24 "uname": "张三", 25 "tel": ["mobile": "138", "home": "010"] 26 ] 27 //首先判断能不能转换 28 if (!NSJSONSerialization.isValidJSONObject(user)) { 29 println("is not a valid json object") 30 return 31 } 32 //利用OC的json库转换成OC的NSData, 33 //如果设置options为NSJSONWritingOptions.PrettyPrinted,则打印格式更好阅读 34 let data : NSData! = NSJSONSerialization.dataWithJSONObject(user, options: nil, error: nil) 35 //NSData转换成NSString打印输出 36 let str = NSString(data:data, encoding: NSUTF8StringEncoding) 37 //输出json字符串 38 println("Json Str:"); println(str) 39 40 //把NSData对象转换回JSON对象 41 let json : AnyObject! = NSJSONSerialization 42 .JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error:nil) 43 println("Json Object:"); println(json) 44 //验证JSON对象可用性 45 let uname : AnyObject = json.objectForKey("uname")! 46 let mobile : AnyObject = json.objectForKey("tel")!.objectForKey("mobile")! 47 println("get Json Object:"); println("uname: \(uname), mobile: \(mobile)") 48 } 49 }
输出结果如下:
1 Json Str: 2 Optional({"uname":"张三","tel":{"home":"010","mobile":"138"}}) 3 Json Object: 4 { 5 tel = { 6 home = 010; 7 mobile = 138; 8 }; 9 uname = "\U5f20\U4e09"; 10 } 11 get Json Object: 12 uname: 张三, mobile: 138
二,使用第三方库 - JSONKit
1 #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 。这样就完成了不支持自动引用计数的配置。
测试代码:
1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading the view, typically from a nib. 8 testJson() 9 } 10 11 override func didReceiveMemoryWarning() { 12 super.didReceiveMemoryWarning() 13 // Dispose of any resources that can be recreated. 14 } 15 16 func testJson() { 17 //Swift 字典对象 18 let user = [ 19 "uname": "user1", 20 "tel": ["mobile": "138", "home": "010"] 21 ] 22 //使用 JSONKit 转换成为 JSON 字符串 23 var jsonstring = (user as NSDictionary).JSONString() 24 println(jsonstring); 25 //由字符串反解析回字典 26 println(jsonstring.objectFromJSONString() as NSDictionary) 27 28 //使用 JSONKit 转换成为 NSData 类型的 JSON 数据 29 var jsondata = (user as NSDictionary).JSONData() 30 println(jsondata); 31 //由NSData 反解析回为字典 32 println(jsondata.objectFromJSONData() as NSDictionary) 33 } 34 }
输出结果:
1 {"uname":"user1","tel":{"home":"010","mobile":"138"}} 2 { 3 tel = { 4 home = 010; 5 mobile = 138; 6 }; 7 uname = user1; 8 } 9 <7b22756e 616d6522 3a227573 65723122 2c227465 6c223a7b 22686f6d 65223a22 30313022 2c226d6f 62696c65 223a2231 3338227d 7d> 10 { 11 tel = { 12 home = 010; 13 mobile = 138; 14 }; 15 uname = user1; 16 }
目前实际开发中使用比较多的是第三方框架来解析的,后面会介绍一个比较好用,而且是大多数程序员比较喜欢的JSON解析框架:SwiftyJSON
-
解析XML格式数据(分别使用GDataXML和DDXML)
在做一些应用的时候经常需要用到XML解析,比如获取Web Service数据,读取RSS新闻或者博客数据源。下面演示了两个非常方便高效的XML库在Swift里的调用方法。
假设需要被解析的XML数据文件users.xml如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <Users> 3 <User id="101"> 4 <name>航歌</name> 5 <tel> 6 <mobile>1234567</mobile> 7 <home>025-8100000</home> 8 </tel> 9 </User> 10 <User id="102"> 11 <name>hangge</name> 12 <tel> 13 <mobile>8989889</mobile> 14 <home>025-8122222</home> 15 </tel> 16 </User> 17 </Users>
我们需要实现的功能是解析并打印出需要的数据:
1 User: uid:101,uname:航歌,mobile:1234567,home:025-8100000 2 User: uid:102,uname:hangge,mobile:8989889,home:025-8122222
一,使用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头文件并设置到编译参数里
1 #import "GDataXMLNode.h"
5,导入GDataXML库文件(GDataXMLNode.h和GDataXMLNode.m),代码结构如下:
6,开始解析(ViewController.swift)
1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading the view, typically from a nib. 8 var label:UILabel = UILabel(frame:CGRectMake(100, 100,300,100)); 9 label.text = "输出结果在控制台" 10 self.view.addSubview(label) 11 //测试Swift调用Object的XML库功能 12 testXML() 13 } 14 15 override func didReceiveMemoryWarning() { 16 super.didReceiveMemoryWarning() 17 // Dispose of any resources that can be recreated. 18 } 19 20 func testXML() { 21 //获取xml文件路径 22 var path = NSBundle.mainBundle().pathForResource("users", ofType:"xml") 23 //获取xml文件内容 24 var xmlData = NSData(contentsOfFile:path!) 25 //可以转换为字符串输出查看 26 //println(NSString(data:xmlData, encoding:NSUTF8StringEncoding)) 27 28 //使用NSData对象初始化文档对象 29 //这里的语法已经把OC的初始化函数直接转换过来了 30 var doc:GDataXMLDocument = GDataXMLDocument(data:xmlData, options : 0, error : nil) 31 32 //获取Users节点下的所有User节点,显式转换为element类型编译器就不会警告了 33 //var users = doc.rootElement().elementsForName("User") as GDataXMLElement[] 34 35 //通过XPath方式获取Users节点下的所有User节点,在路径复杂时特别方便 36 var users = doc.nodesForXPath("//User", error:nil) as [GDataXMLElement] 37 38 for user in users { 39 //User节点的id属性 40 let uid = user.attributeForName("id").stringValue() 41 //获取name节点元素 42 let nameElement = user.elementsForName("name")[0] as GDataXMLElement 43 //获取元素的值 44 let uname = nameElement.stringValue() 45 //获取tel子节点 46 let telElement = user.elementsForName("tel")[0] as GDataXMLElement 47 //获取tel节点下mobile和home节点 48 let mobile = (telElement.elementsForName("mobile")[0] as GDataXMLElement).stringValue() 49 let home = (telElement.elementsForName("home")[0] as GDataXMLElement).stringValue() 50 //输出调试信息 51 println("User: uid:\(uid),uname:\(uname),mobile:\(mobile),home:\(home)") 52 } 53 } 54 }
二,使用DDXML
1,2,3步同上
4,添加bridge.h头文件并设置到编译参数里
1 #import "DDXML.h" 2 #import "DDXMLElementAdditions.h"
5,导入DDXML库文件
6,开始解析(ViewController.swift)
1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading the view, typically from a nib. 8 var label:UILabel = UILabel(frame:CGRectMake(100, 100,300,100)); 9 label.text = "输出结果在控制台" 10 self.view.addSubview(label) 11 //测试Swift调用Object的XML库功能 12 testXML() 13 } 14 15 override func didReceiveMemoryWarning() { 16 super.didReceiveMemoryWarning() 17 // Dispose of any resources that can be recreated. 18 } 19 20 func testXML() { 21 //获取xml文件路径 22 var path = NSBundle.mainBundle().pathForResource("users", ofType:"xml") 23 //获取xml文件内容 24 var xmlData = NSData(contentsOfFile:path!) 25 26 //构造XML文档 27 var doc = DDXMLDocument(data: xmlData, options:0, error:nil) 28 29 //利用XPath来定位节点(XPath是XML语言中的定位语法,类似于数据库中的SQL功能) 30 var users = doc.nodesForXPath("//User", error:nil) as [DDXMLElement] 31 for user in users { 32 let uid = user.attributeForName("id").stringValue() 33 //DDXMLElementAdditions提供了elementForName获取单个节点,不用获取数组了 34 let uname = user.elementForName("name").stringValue() 35 //获取tel节点的子节点 36 let telElement = user.elementForName("tel") as DDXMLElement 37 let mobile = (telElement.elementForName("mobile") as DDXMLElement).stringValue() 38 let home = (telElement.elementForName("home") as DDXMLElement).stringValue() 39 println("User: uid:\(uid),uname:\(uname),mobile:\(mobile),home:\(home)") 40 } 41 } 42 }