前言
Json 和xml是网络开发中经常使用的数据格式,JSON轻量级。xml相对较复杂。所以如今用JSON的比例很大。基本上从server获取的返回数据都是JSON格式的,作为iOS开发人员,解析JSON, XML文件是网络开发最主要的一步,不扯蛋了,直接进入正题。
JSON解析
JSON介绍
JSON 本质上,就是一个”特殊格式”的字符串
- JSON 是网络上用来数据传输使用最广泛的数据格式,没有之中的一个
- JSON 出身草根,是
Javascript
的子集,专门负责描写叙述数据格式
JSON 语法规则
- 数据以 key/value 值对表示
- 数据由逗号分隔
- 花括号保存对象 (字典)
- 方括号保存数组
JSON 存储值
- 数字(整数或浮点数)
- 字符串(在双引號中)
- 逻辑值(true 或 false)
- 数组(在方括号里)
- 对象(在花括号里)
- null
以下看条结构清晰的JSON数据,和上面JSON的特点相应一下:
序列化 & 反序列化
- 序列化:在向server发送数据之前,将
NSArray
/NSDictionary
转换成二进制的过程 - 反序列化:在从server接收到数据之后。将二进制数据转换成
NSArray
/NSDictionary
的过程
JSON 反序列化
- 虎嗅新闻接口
NSURL *url = [NSURL URLWithString:@"http://m.api.huxiu.com/portal/1/1?
client_ver=6&push_type=iOSRel"];
//反序列化
id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
选项 | 说明 |
---|---|
NSJSONReadingMutableContainers = (1UL << 0) |
容器可变 |
NSJSONReadingMutableLeaves = (1UL << 1) |
叶子可变 |
NSJSONReadingAllowFragments = (1UL << 2) |
*节点能够不是 NSArray 或者 NSDictionary |
- 在实际开发中。获得网络的数组或者字典之后,一般会做字典转模型!
反序列化的结果是否可变并不重要
选项选择 0,表示不论什么附加操作都不做,效率最高!
NSJSONSerialization 类
- 专门负责在 JSON 和 Foundation 对象直接转换的类
能够转换成 JSON 的 Foundation 对象须要具备的条件:
* *节点是 NSArray 或者 NSDictionary
* 全部的对象是 NSString, NSNumber, NSArray, NSDictionary 或者 NSNull
* 全部字典的 key 是 NSString
* NSNumber 不是空或者无穷大
JSON解析样例
以下是一个简单的虎嗅新闻的样例:
- 请求的URL: http://m.api.huxiu.com/portal/1/1?client_ver=6&push_type=iOSRel
- 返回JSON数据并对JOSN数据解析
- 打印出第一条新闻
我们先来看下URL实际返回的JSON是什么样子的:
在线 JSON解析的站点:http://json.cn
演示样例代码用swift 写的。亲们看下Swift 代码是不是比OC美丽多了。而且今年swift2.0就要开源了喽,博主难以掩饰对swift的喜爱。哈哈
有木有发现swift的代码使用起来和OC很像,使用函数的名字基本一致。仅仅只是那个讨厌的
[]
变成了让人喜爱的.
语法,大爱。
假设对swift感兴趣,能够兴许看下blog中swift系列的文章
好了言归正传,亲们看下以下的JSON解析是不是很easy:
func readJson()
{
//这个是虎嗅新闻看点的API
let url = NSURL(string: "http://m.api.huxiu.com/portal/1/1?client_ver=6&push_type=iOSRel")!
let request = NSURLRequest(URL: url)
//用NSURLConnection 做异步请求
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (_, data, error) -> Void in
if (data == nil || error != nil)
{
println("网络不给力")
return
}
//依据数据格式能够知道返回的是一个字典(有的站点会返回数组,比較少见)
let resultDic = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as! NSDictionary
//获取内容部分,内容的key-> 'content', value:是个数组
let resultArray = resultDic["content"] as! NSArray
//这里我们仅仅看第一条新闻。也能够遍历数组查看全部的内容
let result = resultArray[0] as! NSDictionary;
//依据key 提取我们想要的内容
let cityName = result["img"] as! String
let author = result["author"] as! String
let title = result["title"] as! String
let summary = result["summary"] as! String
println("虎嗅新闻 \n作者:\(author)\n标题:\(title) \n摘要:\(summary) ")
}
}
上面结果输出:
虎嗅新闻
作者:虎嗅
标题:综艺节目大爆炸。电视台和视频站点过得好吗
摘要:要赚钱,还要领导放心,观众惬意,可真够难的。
来看下手机app上的结果。是不是一样滴:
注意:
上面请求使用的swift 闭包
{ (_, data, error) -> Void in}
来进行JSON数据解析,代码运行的顺序为:readJson函数-> 网络异步请求-> readJson 函数运行完毕-> server返回Json数据-> 回调闭包中代码块进行JSon数据解析。看吧,闭包和OC的block很想吧。实际上swift闭包功能更强大。
JSON解析-第三方框架
常见的 JSON 解析第三方框架
- JSONKit(最快)
- SBJson
- TouchJSON
上面三个框架的性能依次减少。所以我们仅仅说一下JSONKit
JSONKit
使用步骤步骤
-
导入框架文件
- JSONKit.h
- JSONKit.m
-
设置 MRC 标记(JSONKit 基于MRC的)
- 选择”项目”-”Build Phases”-”Compile Sources”
- 找到 JSONKit.m 而且在 Compiler Flags 中加入
-fno-objc-arc
。 能够告诉编译器,编译 JSONKit.m 时不使用 ARC
-
改动错误
- 利用自己主动修复功能。改动两处 isa 的错误
反序列化
使用起来很easy。创建一个decoder对象,调用解析方法就能够
id result = [[JSONDecoder decoder] objectWithData:data];
注意
:
JSONKit 仅仅支持iOS5.0之前的系统,是MRC下的框架。所以新项目不要使用
JSONKit 2012已经停止更新。当时apple官方说JSONKit 的效率要高于系统自带的JSON解析,只是要知道苹果对于自身系统的优化更新是很快的,眼下的apple原生态的JSON解析已经完爆JSONKit了。假设你如今还在用他,建议换成系统自身的JSON解析。
苹果新系统强制推广的速度很快。随着更新,许多以前的东西会被更好的替代,NSURLConnection 就是一个样例。所以程序员要跟上时代的潮流啊
XML解析
XML 介绍
- XML的特点,出身名门,W3C制定,微软和IBM以前共同大力推荐过的数据格式
- XML 指可扩展标记语言(eXtensible Markup Language)
- 被设计用来传输和存储数据
让我来看下XML数据,瞬间有木有想感觉信息量好大:
<?xml version="1.0" encoding="UTF-8"?
>
<Books>
<Book id="1">
<title>Circumference</title>
<author>Nicholas Nicastro</author>
<summary>Eratosthenes and the Ancient</summary>
</Book>
<Book id="2">
<title>Copernicus Secret</title>
<author>Jack Repcheck</author>
<summary>How the scientific revolution began</summary>
</Book>
<Book id="3">
<title>Angels and Demons</title>
<author>Dan Brown</author>
<summary>Robert Langdon is summoned to a Swiss</summary>
</Book>
</Books>
XML 解析的方式
DOM 解析
- 是在 MAC上使用的解析方式
- 内存消耗极大,不适用于手机
- iPhone无法直接使用 DOM 方式解析 XML
SAX 解析
- 是仅仅读的方式,从上向下的方式解析
- 是苹果提供的解析方式
- 速度快
- NSXMLParser 通过
代理
实现解析
SAX 解析步骤
- 開始文档 - 准备工作
- 開始”节点”
- 发现节点内部的内容。每个节点,可能须要多次才干找完
- 结束”节点”
- 结束文档 - 解析结束
以上步骤,2。3。4。会不断循环,一直到全部解析完毕!
事实上解析本质上就是不断循环遍历节点,获取节点内容。由于XML的节点格式是成对出现的。只是节点的名字是自己定义的,这也是解析难点所在。
1. loadData
- (void)loadData {
NSURL *url = [NSURL URLWithString:@"http://localhost/books.xml"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 异步解析 XML
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 1. 使用网络返回的二进制数据实例化 NSXMLParser 对象
NSXMLParser *ZHParser = [[NSXMLParser alloc] initWithData:data];
// 2. 设置代理,通过代理方法实现 SAX 解析
ZHParser.delegate = self;
// 3. 開始解析
[ZHParser parse];
}];
}
使用代理方法获取数据
仅仅要没有碰到文档的结束符。解析器就会循化运行2,3,4方法,直到所以后的数据解析完
// MARK: - NSXMLParserDelegate
// 1. 開始文档 - 准备工作
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(@"1. 開始文档");
}
// 2. 開始节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
NSLog(@"2. 開始节点 %@ %@", elementName, attributeDict);
}
// 3. 发现文字
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"==> %@", string);
}
// 4. 结束节点
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(@"4. 结束节点 %@", elementName);
}
// 5. 结束文档 - 解析结束
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(@"5. 解析结束");
}
// 6. 错误处理
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
NSLog(@"解析错误 %@", parseError);
}
SAX & DOM 解析对照
SAX 特点
- 仅仅读
- 从上向下
- 速度快
- 解析的时候相对照较繁琐,有5个代理方法。每个代理方法都要写一定代码
- 适合大的 XML 文件解析
总的来说。SAX仅仅在xml文档中查找特定条件的内容。而且仅仅提取须要的内容。这样做占用内存小,灵活。
DOM 特点
-
背景
- 主要用在 PC 端或者server端
- 苹果提供了
NSXML
类支持DOM
方式的解析 - 只是
NSXML
类仅仅能用在MAC
开发。在iOS
中无法直接使用 - DOM 方式不仅能解析 XML 文档,还能够改动: 添加节点/删除节点
-
实现
- 一次性将 XML 文档以树形结构读入内存
- 横向的节点越多,内存消耗越大
- 使用 DOM 解析适合于小的 XML 解析,而且能够动态维护
- 有些第三方框架就提供了 DOM 方式的解析,
GData
/KissXML
(XMPP) - 在 iOS 开发中,假设要使用 DOM 方式解析,最好仅仅处理小的 XML
GData解析XML
GDataXMLNode是Google提供的用于XML数据处理的类集。该类集对libxml2-DOM处理方式进行了封装,能对较小或中等的XML文档进行读写操作且支持XPath语法。 原理上和DOM同样。
GData解析步骤
- 获得根节点。依次 Log,一定要确认能够拿到全部子节点的内容
- 横向节点越多,for的层次就越深
- 依据实际的 XML 的情况,确认解析
准备工作
- 訪问 http://code.google.com/p/gdata-objectivec-client/source/browse/trunk/Source/XMLSupport/, 获得GDataXMLNode.h和GDataXMLNode.m 文件
- 将GDataXMLNode.h/m文件加入到project中
- 向project中添加“libxml2.dylib”库。
- 在project的“Build Settings”页中找到“Header Search Path”项,加入“/usr/include/libxml2”到其路径
GData使用演示样例
XML数据
<?xml version="1.0"?>
<xml_api_reply version="1">
<cities>
<city>
<name data="保定"/>
<latitude_e6> 38849998</latitude_e6>
<longitude_e6> 115569999</longitude_e6>
</city>
<city default="true" >
<name data="北京"/>
<latitude_e6> 39930000</latitude_e6>
<longitude_e6> 116279998</longitude_e6>
</city>
<city>
<name data="沈阳"/>
<latitude_e6> 41770000</latitude_e6>
<longitude_e6> 123430000</longitude_e6>
</city>
<city>
<name data="成都"/>
<latitude_e6> 30670000</latitude_e6>
<longitude_e6> 104019996</longitude_e6>
</city>
<city>
<name data="大连"/>
<latitude_e6> 38900001</latitude_e6>
<longitude_e6> 121629997</longitude_e6>
</city>
<city>
<name data="福州"/>
<latitude_e6> 26079999</latitude_e6>
<longitude_e6> 119279998</longitude_e6>
</city>
</cities>
</xml_api_reply>
解析方法
首先分析下数据层次结构:
<?
xml version="1.0"?> : </xml_api_reply>
<cities> : </cities>
<city> : </city>
依据上面的节点来解析数据。要有两个for循环
- (void)parseCitys
{
NSData *xmlCitysData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"citys" ofType:@"xml"]];
// 读取data在内存中形成完整的树形结构
NSError * error = nil;
GDataXMLDocument * documents = [[GDataXMLDocument alloc]initWithData:xmlCitysData options:0 error:&error];
// 取得根节点
GDataXMLElement *rootNode = [documents rootElement];
//获取根节点xml_api_reply的数组,包括的是cities,假设根节点不知有一个数组。就又要遍历
NSArray * citiesArray = [rootNode elementsForName:@"cities"];
for (int i = 0; i < [citiesArray count]; i++) {
// 取得单个cities节点
GDataXMLElement * cities = [citiesArray objectAtIndex:i];
//获取节点cities的数组,包括的是city
//看出规律了吧,通过当前GDataXMLElement和子节点的name,能够获取子节点的数组
NSArray * cityArray = [cities elementsForName:@"city"];
for (int j = 0; j < [cityArray count]; j++) {
// 取得单个city节点
GDataXMLElement * city = [cityArray objectAtIndex:j];
//节点以下是3个并行的节点,都是1个,直接通过lastObject来取得想要的值
NSString * name = [[[[city elementsForName:@"name"]lastObject] attributeForName:@"data"] stringValue];
NSLog(@"name = %@",name);
NSString * latitude_e6 = [[[city elementsForName:@"latitude_e6"]lastObject] stringValue];
NSLog(@"latitude_e6 = %@",latitude_e6);
NSString * longitude_e6 = [[[city elementsForName:@"longitude_e6"]lastObject] stringValue];
NSLog(@"longitude_e6 = %@",longitude_e6);
}
}
}
PList解析
PList 主要在苹果开发中经常使用。比方那个新建项目都会自带一个info.plist,事实上全部的数据格式都是相通的,无非存储数组。字典。对象,好的数据格式就是易于存储,易于读写。
这里最后简介下plist, 毕竟大部分server后台并不会返回 PList 的数据格式。
/**
參数
1. data: 要反序列化的二进制数据
2. option: 选项,位移枚举类型
NSPropertyListImmutable = 0, 不可变
NSPropertyListMutableContainers = 1, 容器可变
NSPropertyListMutableContainersAndLeaves = 2 容器和叶子可变
3. format: 假设不希望知道格式。传入 NULL 就可以
4. error: 错误
*/
id result = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL];
兴许阅读
JSON与XML的差别比較
http://blog.csdn.net/hmt20130412/article/details/240482972.XML解析类库对照和安装说明
http://blog.csdn.net/hmt20130412/article/details/24048719
玩转iOS开发 - JSON 和 Xml 数据解析的更多相关文章
-
iOS开发——网络Swift篇&;JSON与XML数据解析
JSON与XML数据解析 JSON数据解析(内置NSJSONSerialization与第三方JSONKit) 一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SD ...
-
iOS开发网络篇—XML数据的解析
iOS开发网络篇—XML数据的解析 iOS开发网络篇—XML介绍 一.XML简单介绍 XML:全称是Extensible Markup Language,译作“可扩展标记语言” 跟JSON一样,也是 ...
-
iOS-数据持久化基础-JSON与XML数据解析
解析的基本概念 所谓“解析”:从事先规定好的格式串中提取数据 解析的前提:提前约定好格式.数据提供方按照格式提供数据.数据获取方按照格式获取数据 iOS开发常见的解析:XML解析.JSON解析 一.X ...
-
iOS开发网络篇之Web Service和XML数据解析
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...
-
iOS - XML 数据解析
前言 @interface NSXMLParser : NSObject public class NSXMLParser : NSObject 1.XML 数据 XML(Extensible Mar ...
-
iOS学习笔记(九)——xml数据解析
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...
-
iOS学习笔记(九)—— xml数据解析
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...
-
玩转iOS开发:iOS中的GCD开发(三)
上一章, 我们了解到了GCD里的一些队列和任务的知识, 也实践了一下, 同时我们也对主队列的一些小情况了解了一下, 比如上一章讲到的卡线程的问题, 如果没有看的朋友可以去看看玩转iOS开发:iOS中的 ...
-
php生成json或者xml数据
, ,'数据返回成功',$arr);echo $xml;?>
随机推荐
-
UITabBarController 更改tabbariteam上的选中图片
首先遵守“ UITabBarControllerDelegate ”协议 再在- (void)viewDidLoad {}方法中设置代理“ self.tabBarController.delegate ...
-
回顾yii的学习进程 总结了一下的发展过程
如果看到这篇文章,我想说恭喜你 不用,你可以先放下学习yii了 我先学在把结论发给你们节省精力 yii2的学习教程:http://www.digpage.com/recent_update.html ...
-
eclipse下的emacs风格快捷键
Ieclipse emacs类快捷键 win + shift + b 切换设置断点 win + shift + f 格式化代码 win + shift + l 显示绑定的快捷键 win + shift ...
-
Sqli-LABS通关笔录-11[sql注入之万能密码以及登录框报错注入]
在这一关卡我学到了 1.万能密码的构造,大概的去揣测正常的SQL语句是如何的. 2. 3. 00x1 SQL万能密码的构造 在登录框当中可以添加了一个单引号.报错信息如下所示: 据此报错,我们大概的可 ...
-
java5 Lock用法
锁是控制多个线程对共享资源进行访问的工具.通常,锁提供了对共享资源的独占访问.一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁.不过,某些锁可能允许对共享资源并发访问,如 ReadWri ...
-
【codevs2216】行星序列 线段树 区间两异同修改+区间求和*****
[codevs2216]行星序列 2014年2月22日3501 题目描述 Description “神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小 ...
-
java基础知识—数组
1.数组:是一个变量,存储相同数据类型的一组数据. 2.数据的优点:减少代码量.易查找. 3.数组的使用步骤: 1)声明数组:int scores []: 2)开辟空间:scores = new in ...
-
SignalR 2.x入门(二):SignalR在MVC5中的使用
开发(代码下载) 新建一个ASP.NET Web项目,项目类型为MVC,将认证模式改为无身份认证.在程序包管理控制台输入如下语句,安装SignalR <span style="font ...
-
SSD 相关基础知识
SDD 基础知识 SSD(Solid State Drives)是固态硬盘,使用闪存颗粒来存储数据,闪存又可分为NAND Flash和NOR Flash,通常所说的SSD硬盘都使用NAND Flash ...
-
git设置别名alias
每次用git拉去版本库都很烦,特别是要从非origin源,非master分支, 例如 git pull gitlab mybranch ,这样很蛋疼. 1.写个sh去处理 2.可以通过git的别名设置 ...