现大多公司使用接口数据都是json格式,但也有少量很老的系统还是使用XML格式来传递数据,相对来传递一样的数据json格式的数据比使用xml传递更小。简单说说json、及xml的解析
JSON
什么是json?
首先来说说什么是json。
- json是一种轻量级的数据格式,一般用于数据交互;服务器方会给客户端的数据,一般都是json格式或者xml(文件下载除外)
- JSON的格式很像OC中的数组和字典,如下
{"name":"张三","age":22}、[{"name":"张三","age":22},{"name":"李四","age":22}]
- 标准的JSON格式key必须用双引号
在开发过程中,有些服务端同学偷懒会使用单引号,这种在javaScript
和安卓开发是能正常解析的,但iOS不行,遇到该种情况一定要强烈要求使用标准格式
JSON数据看上去像字典或数组,但实际上是一串字符串,想要使用它需要进行解析。
JSON转换OC数据类型对应表
JSON | OC |
---|---|
{} | NSDictionary |
[] | NSArray |
双引号"" | NSString |
数字0、1、2 | NSNumber |
true、false | NSNumber (0,1) |
null | NSNull 为空 |
解析JSON一种使用原生自带NSJSONSerialization
,一种使用第三方框架JSONKit、SBJson、TouchJSON
这三个框架性能逐次变差;原生解析性能是最好的,NSJSONSerialization
在ios7推出macOS 10.9推出,此版本之前的json解析需要第三方
NSJSONSerialization解析
NSJSONSerialization
常见方法
JSON数据转OC对象
+ JSONObjectWithData:options:error:
json data数据转换成oc对象(NSDictionary、NSArray)JSONObjectWithStream:options:error:
json数据流转换成oc对象- 两个方法都有使用到
NSJSONReadingOptions
参数,该参数用于表明NSJSONReadingMutableContainers
指定将数组和字典创建为可变对象NSJSONReadingMutableLeaves
指定json数据中内部所有字符串数据创建为NSMutableString(一般不使用)NSJSONReadingAllowFragments
即不是字典也不是数组,则必须使用该枚举值(如数据为"这是数据"将会解析对应的NSString
)
NSString *jsonStr = @"{\"name\":\"张三\",\"age\":24}";
NSData *jsonData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
NSError *error=nil;
NSMutableDictionary *ocInstance = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
[ocInstance setObject:@(12) forKey:@"child"];
注意,通常枚举的第一个枚举值不等于0的话传入0效率最高
OC对象转JSON数据方法
+ dataWithJSONObject:options:error:
从oc对象返回JSON数据。+ isValidJSONObject:
返回一个布尔值,该值指示是否可以将给定对象转换为JSON数据+ writeJSONObject:toStream:options:error:
将给定的JSON对象写入流中。不常用
上述两个转换方法中都有使用到NSJSONWritingOptions
枚举,枚举含义如下NSJSONWritingPrettyPrinted = (1UL << 0)
使用空格和缩进的写入选项使输出更具可读性NSJSONWritingSortedKeys API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0)) = (1UL << 1)
按字典顺序对键进行排序的写入选项NSJSONWritingFragmentsAllowed = (1UL << 2)
允许写入片段非标准如@"要转换的数据"
。NSJSONWritingWithoutEscapingSlashes API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0)) = (1UL << 3)
不转义斜线
NSDictionary *dic = @{@"name":@"张三",
@"age":@(24),
@"child":@{@"name":@"张小三",
@"age":@(2)}
};
NSData *jsonData=[NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
NSString *json= [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"%@",json);
注意,通常枚举的第一个枚举值不等于0的话传入0效率最高
XML
XML 指可扩展标记语言
XML 被设计用来传输和存储数据。
XML由以下几部分构成
- 文档声明(通常可忽略不计)
- 元素(Element)
- 属性(Attribute)
文档声明
文档声明在xml文档的最前面,必须编写一个文档声明,用来声明xml文档的类型
<?xml version="1.0" ?>
最简单的声明,用encoding
属性说明文档的字符编码<?xml version="1.0" encoding="utf-8"?>
元素(Element)
- 一个元素包括了开始标签和结束标签
- 有内容的元素
<from>John</from>
- 没内容的元素
<from></from>
,可简写成<from/>
- 元素可嵌套其他元素,不可出现交叉嵌套。
<note>
<to>George</to>
<from>John</from>
</note>
- 规范的xml文档最多只有一个根元素,其他元素都是根元素的子孙节点
<from>John</from>
与
<from>
John
</from>
是不一样的,第二个的空格和换行符也是元素的内容
属性
- 一个元素可以有多个属性
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
在这个里面book里面有个category属性,title有lang属性。
- 属性必须使用双引号
""
或者单引号''
包住 - 属性表示的信息也可以用子元素来表示比如
<book >
<category>COOKING</category>
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
XML解析
要想从xml中提取信息,就得解析xml;解析xml有两种方式
DOM
解析:一次性将xml文档加载进内存,比较合适解析小的xml文档SAX
解析:从根元素开始,按顺序一个元素逐次解析,比较合适解析大文件
ios解析xml中有两种
- 苹果原生,使用
NSXMLParse
:SAX方式解析,使用简单 - 第三方框架:
libxml2、GDataXML
libxml2
纯c语音,默认包含在iOS SDK中,同时支持DOM和SAX方式解析GDataXML
DOM解析,由google基于libxml2开发,
解析xml大文件建议使用```NSXMLParse、libxml2``;小文件上述三种可
NSXMLParse 使用
- 创建
NSXMLParse
解析器 - 设置代理
- 开始解析
NSXMLParse
解析是在代理里面开始的
常用解析的代理方法如下
- parserDidStartDocument:
开始解析- parserDidEndDocument:
成功完成解析后- parser:didStartElement:namespaceURI:qualifiedName:attributes:
当解析器对象遇到元素的开始标签时- parser:didEndElement:namespaceURI:qualifiedName:
当解析器对象元素的结束标签时- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
当解析器找到开始标记和结束标记之间的字符时,调用这个方法解析当前节点的所有字符
附上使用NSXMLPares的简单封装XMLParseDome,该Dome将xml解析出的内容封装到了XPDXMLElement