JSON
-
JSON
是一种轻量级
的数据格式,一般用于数据交互。 - 服务器返回给客户端的数据,一般都是
JSON格式
或者XML格式
(文件下载除外)。 -
JSON
的格式很像OC中
的字典
和数组
。
{"name" : "jack", "age" : 10}
{"names" : ["jack", "rose", "jim"]}
标准JSON格式的
注意点
:key必须用双引号
。要想从
JSON
中挖掘出具体数据,得对JSON
进行解析。
JSON
转换为OC
数据类型
-
JSON – OC
转换对照表
JSON | OC |
---|---|
大括号 { } | NSDictionary |
中括号 [ ] | NSArray |
双引号" "
|
NSString |
数字 10、10.8 | NSNumber |
-
JSON – OC
转换练习
JSON
解析方案
- 在
iOS
中,JSON
的常见解析方案有4
种.
a、第三方框架:JSONKit、SBJson、TouchJSON
(性能从左到右,越差) 。
b、苹果原生(自带):NSJSONSerialization
(性能最好
)。
-
NSJSONSerialization
的常见方法: -
JSON
数据 -->OC
对象(字典|数组)[反序列化处理]
+(id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
//JSONData - >OC中的对象(字典|数组) [反序列化处理]
-(void)jsonToOC
{
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//处理服务器返回的数据
//01 JSONData - > NSString
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
//02 JSONData - >OC中的对象(字典|数组)
/* 参数说明
*
* 第一个参数:要解析的json数据
* 第二个参数:解析数据时候附加的选项 默认传0
* NSJSONReadingMutableContainers = (1UL << 0), 得到的对象是可变的
* NSJSONReadingMutableLeaves = (1UL << 1), 得到的对象中字符串是可变的
* NSJSONReadingAllowFragments = (1UL << 2) ! 当返回的对象既不是字典也不是数组的时候(null)
* 第三个参数:错误信息
*/
NSDictionary * obj = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@--%@",[obj class],obj);
/*
[NSNull null]; //空对象
nil //空
//NSNull *null = [NSNull null];
//NSDictionary *dict = @{@"name":@"xiaoma",@"age":[NSNull null]};
*/
}] resume];
}
-
OC
对象(字典|数组) -->JSON
数据[序列化处理]
+(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
//OC中的对象(字典|数组) - >JSONData[序列化处理]
-(void)ocToJSON
{
//注意:并不是所有的OC对象都支持转换为JSON
//NSDictionary *dict = @{@"name":@"xiaoming",@"age":@25};
//NSArray *array = @[@"wen",@"xioamage",@"dangdang"];
NSString *string = @"我恨你!";
/*
- 最外层的对象必须是 an NSArray or NSDictionary
- 字典或数组中所有的元素只能是NSString, NSNumber, NSArray, NSDictionary, or NSNull
- 字典中所有的key都必须是 NSStrings
- NSNumbers 是标准的并且不能是无穷大
*/
if (![NSJSONSerialization isValidJSONObject:string]) {
NSLog(@"该对象不支持转换");
return;
}
/* 参数说明
*
* 第一个参数:要序列化的OC对象
* 第二个参数:选项
*/
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:string options:kNilOptions error:nil];
NSLog(@"%@",[[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding]);
}
- 将数据写成
Json
格式的文件
-(void)other
{
//01 加载数据
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
//02 把数据以json的方式来保存
//写plist文件
//[array writeToFile:@"/Users/xiaomage/Desktop/123.plist" atomically:YES];
//写json文件 错误的写法
//[array writeToFile:@"/Users/xiaomage/Desktop/123.json" atomically:YES];
//需要先把OC对象转换成jsonData 然后再写文件
//NSJSONWritingPrettyPrinted 排版美化结构
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:nil];
//03 写文件
[jsonData writeToFile:@"/Users/nana/Desktop/123.json" atomically:YES];
}
-
Json
文件中的数据转换成OC对象
-(void)other2
{
//01 加载数据
NSData *jsonData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"123.json" ofType:nil]];
//02 jsonData - >OC对象
NSArray *array = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
//03 打印输出
NSLog(@"%@",array);
}
- 解析来自服务器的
JSON
XML
- 什么是
XML
?
a.全称是E
x
tensibleM
arkupL
anguage,译作“可扩展标记语言”
。
b.跟JSON
一样,也是常用的一种用于交互的数据格式
。
c.一般也叫XML
文档(XML Document
)。
-
XML
举例:
<videos>
<video name="小黄人 第01部" length="30" />
<video name="小黄人 第02部" length="19" />
<video name="小黄人 第03部" length="33" />
</videos>
- XML语法:
- 一个常见的XML文档一般由以下部分组成:
1.文档声明
2.元素(Element)
3.属性(Attribute)
- 1.
XML
语法 – 文档声明
1.1、在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型
最简单的声明
<?xml version="1.0" ?>
1.2、用encoding
属性说明文档的字符编码
<?xml version="1.0" encoding="UTF-8" ?>
- 2.
XML
语法 – 元素(Element
)
- 2.1、一个元素包括了开始标签和结束标签
a.拥有内容的元素:<video>小黄人</video>
b.没有内容的元素:<video></video>
c.没有内容的元素简写:<video/>
- 2.2、一个元素
可以嵌套若干个
子元素(不能出现交叉嵌套
)
<videos>
<video>
<name>
小黄人 第01部</name>
<length>
30</length>
</video>
</videos>
- 2.3、规范的
XML
文档最多只有1个根元素
,其他元素
都是根元素
的子孙元素
。
XML
语法 –元素的注意:
XML
中的所有空格
和换行
,都会当做具体内容
处理。
下面两个元素的内容是不一样的:
第1个
<video>
小黄人</video>
第2个
<video>
小黄人
</video>
- 3.
XML
语法 – 属性(Attribute
)
- 3.1、 一个元素可以拥有多个属性:
a.<videoname
="小黄人 第01部"length
="30" />。
b.video
元素拥有name
和length
两个属性。
c.属性值
必须用双引号""
或者单引号''
括住。
- 3.2、实际上,
属性表示的信息
也可以用子元素来
表示,比如
<video>
<name>
小黄人 第01部</name>
<length>
30</length>
</video>
XML解析
- 要想从XML中提取有用的信息,必须得学会解析XML
a、提取
name
元素里面的内容。
<name>
小黄人 第01部</name>
b、提取video
元素中name
和length
属性的值。
<videoname
="小黄人 第01部"length
="30" />
- XML的解析方式有2种
DOM
:一次性将整个XML
文档加载进内存
,比较适合解析小文件
。
SAX
:从根元素
开始,按顺序一个元素一个元素
往下解析,比较适合解析大文件
。
- iOS中的
XML
解析
- 在iOS中,解析
XML
的手段有很多:
1、苹果原生
NSXMLParser
:SAX
方式解析,使用简单。
2、第三方框架
libxml2
:纯C
语言,默认包含在iOS SDK
中,同时
支持DOM
和SAX
方式解析。
GDataXML
:DOM
方式解析,由libxml2
。
XML
解析方式的选择建议:
大文件
:NSXMLParser
、libxml2
。
小文件
:GDataXML
、NSXMLParser
、libxml2
。
-NSXMLParser
- 使用步骤
01.传入XML数据,创建解析器
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
02.设置代理,监听解析过程
parser.delegate = self;
03.开始解析
[parser parse];
-
NSXMLParser
采取的是SAX
方式解析,特点是事件驱动,下面情况都会通知代理
。
1、当扫描到
文档
(Document
)的开始与结束。
2、当扫描到元素
(Element
)的开始与结束。
NSXMLParserDelegate
01、当
扫描到文档
的开始
时调用(开始解析
)
- (void)parserDidStartDocument:(NSXMLParser *)parser;
02、当
扫描到文档
的结束
时调用(解析完毕
)
- (void)parserDidEndDocument:(NSXMLParser *)parser;
03、当
扫描到元素
的开始
时调用(attributeDict
存放着元素的属性
)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
04、当
扫描到元素
的结束
时调用
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
#import "ViewController.h"
#import "UIImageView+WebCache.h"
#import <MediaPlayer/MediaPlayer.h>
#import "XMGVideo.h"
#import "MJExtension.h"
#define KbaseUrlString @"http://120.25.226.186:32812/"
@interface ViewController ()<NSXMLParserDelegate>
@property (nonatomic,strong) NSMutableArray *videos;
@end
@implementation ViewController
-(NSMutableArray *)videos
{
if (_videos == nil) {
_videos = [NSMutableArray array];
}
return _videos;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//01 确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
//02 创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//03 创建TASK 执行Task
[[session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//在进行字典转模型之前手动的设置替换 ID - id
[XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{@"ID":@"id"};
}];
//04 解析服务器返回的数据
//001 创建XML解析器(NSXMLParser-SAX)
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
//002 设置代理
parser.delegate = self;
//003 开始解析 本身是阻塞式的
[parser parse];
//06 刷新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.tableView reloadData];
}];
}] resume];
}
#pragma mark -----------------------
#pragma mark UItableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.videos.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//01 获得cell
static NSString *ID = @"video";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//02 设置cell
//001 得到该行cell对应的数据
XMGVideo *videoM = self.videos[indexPath.row];
//002 设置标题和子标题
cell.textLabel.text = videoM.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"播放时间:%@",videoM.length];
//003 设置图片
NSString *urlString = [KbaseUrlString stringByAppendingString:videoM.image];
NSURL *url = [NSURL URLWithString:urlString];
[cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"Snip20161125_180"]];
NSLog(@"%@",videoM.ID);
//03 返回cell
return cell;
}
#pragma mark -----------------------
#pragma mark UItableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//01 得到对应的数据
XMGVideo *videoM = self.videos[indexPath.row];
NSString *urlString = [KbaseUrlString stringByAppendingString:videoM.url];
NSURL *url = [NSURL URLWithString:urlString];
//02 创建视频播放控制器
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc]initWithContentURL:url];
//03 弹出播放器
[self presentViewController:vc animated:YES completion:nil];
}
#pragma mark -----------------------
#pragma mark NSXMLParserDelegate
//01 开始解析XML文档的时候调用
-(void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidStartDocument");
}
//02 开始解析XML文档中某个元素的时候调用 该方法会调用多次
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{
NSLog(@"didStartElement--开始解析的元素名称:%@\n%@",elementName,attributeDict);
//过滤掉根元素
if ([elementName isEqualToString:@"videos"]) {
return;
}
//001 把字典转换为模型
XMGVideo *video = [XMGVideo mj_objectWithKeyValues:attributeDict];
//002 把模型添加到全局的可变数组中保存起来
[self.videos addObject:video];
}
//03 某个元素解析完毕之后会调用该方法
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSLog(@"didEndElement");
}
//04 整个XML文档解析完毕
-(void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidEndDocument");
}
@end
GDataXML
-
GDataXML
基于libxml2
库,得做以下配置:
1、导入
libxml2
库
2、设置
libxml2
的头文件搜索路径(为了能找到libxml2
库的所有头文件)
a、在Head Search Path中加入/usr/include/libxml2
。
3、设置链接参数(自动链接
libxml2
库)
a、在Other Linker Flags
中加入-lxml2
。
4、由于
GDataXML
是非ARC
的,因此得设置编译参数
-
GDataXML
使用
1、
GDataXML
中常用的类:
1.1、GDataXMLDocument
:代表整个XML
文档
1、 把整个XML文档加载进内存
GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:data options:kNilOptions error:nil];
2、
GDataXMLElement
2.1、代表文档
中的每个元素
。
2.2、使用attributeForName:
方法可以获得属性值
。
2 先得到根元素,然后获取根元素内部所有名称为video的子元素
GDataXMLElement *rootElement = doc.rootElement;
NSArray *eles = [rootElement elementsForName:@"video"];
//03 遍历整个子元素数组,然后得到数组中每个元素的内部属性
for (GDataXMLElement *ele in eles) {
//创建模型
XMGVideo *video = [[XMGVideo alloc]init];
//得到子元素的属性
video.name = [ele attributeForName:@"name"].stringValue;
video.ID =[ele attributeForName:@"id"].stringValue;
video.length =[ele attributeForName:@"length"].stringValue;
video.image = [ele attributeForName:@"image"].stringValue;
video.url = [ele attributeForName:@"url"].stringValue;
//把模型保存到数据源
[self.videos addObject:video];
}
示例代码:
#import "ViewController.h"
#import "UIImageView+WebCache.h"
#import <MediaPlayer/MediaPlayer.h>
#import "XMGVideo.h"
#import "MJExtension.h"
#import "GDataXMLNode.h"
#define KbaseUrlString @"http://120.25.226.186:32812/"
@interface ViewController ()
@property (nonatomic,strong) NSMutableArray *videos;
@end
@implementation ViewController
-(NSMutableArray *)videos
{
if (_videos == nil) {
_videos = [NSMutableArray array];
}
return _videos;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//01 确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
//02 创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//03 创建TASK 执行Task
[[session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//在进行字典转模型之前手动的设置替换 ID - id
[XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{@"ID":@"id"};
}];
//04 解析服务器返回的数据 XML
//001 把整个XML文档加载进内存
GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:data options:kNilOptions error:nil];
//002 先得到根元素,然后获取根元素内部所有名称为video的子元素
GDataXMLElement *rootElement = doc.rootElement;
NSArray *eles = [rootElement elementsForName:@"video"];
//03 遍历整个子元素数组,然后得到数组中每个元素的内部属性
for (GDataXMLElement *ele in eles) {
//创建模型
XMGVideo *video = [[XMGVideo alloc]init];
//得到子元素的属性
video.name = [ele attributeForName:@"name"].stringValue;
video.ID =[ele attributeForName:@"id"].stringValue;
video.length =[ele attributeForName:@"length"].stringValue;
video.image = [ele attributeForName:@"image"].stringValue;
video.url = [ele attributeForName:@"url"].stringValue;
//把模型保存到数据源
[self.videos addObject:video];
}
//06 回到主线程刷新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self.tableView reloadData];
}];
}] resume];
}
#pragma mark -----------------------
#pragma mark UItableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.videos.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//01 获得cell
static NSString *ID = @"video";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//02 设置cell
//001 得到该行cell对应的数据
XMGVideo *videoM = self.videos[indexPath.row];
//002 设置标题和子标题
cell.textLabel.text = videoM.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"播放时间:%@",videoM.length];
//003 设置图片
NSString *urlString = [KbaseUrlString stringByAppendingString:videoM.image];
NSURL *url = [NSURL URLWithString:urlString];
[cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"Snip20161125_180"]];
NSLog(@"%@",videoM.ID);
//03 返回cell
return cell;
}
#pragma mark -----------------------
#pragma mark UItableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//01 得到对应的数据
XMGVideo *videoM = self.videos[indexPath.row];
NSString *urlString = [KbaseUrlString stringByAppendingString:videoM.url];
NSURL *url = [NSURL URLWithString:urlString];
//02 创建视频播放控制器
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc]initWithContentURL:url];
//03 弹出播放器
[self presentViewController:vc animated:YES completion:nil];
}
@end
JSON和XML比较
同一份数据
,既可以用JSON
来表示,也可以用XML
来表示。
相比之下,
JSON
的体积小于XML
,所以服务器返回给移动端的数据格式
以JSON
居多。
以上内容,为本人结合相关课程的总结解析的相关的知识点,如有错误敬请批正......