一 JSON
1 JSON的基本概念
1 ) JSON是一种轻量级的数据格式,一般用于数据交互
2 ) JSON的格式很像OC中的字典和数组
3 ) 要想从JSON中挖掘具体数据,得对JSON进行解析
二 JSON解析数据
1 JSON转OC对象,解析(反序列化)
2 相关代码 :
#pragma mark - JSON转化为OC
- (void)jsonToOc
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
id obj = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@------%@",obj,[obj class]);
}];
[dataTask resume];
}
3 OC对象转JSON,解析(序列化)
注意 : 转的时候需要做出判断,判断OC对象符不符合转JSON的条件
4 相关代码:
#pragma mark - 序列化
- (void)ocToJson
{
NSArray *obj = @[@122,@3222,@22225];
if ([NSJSONSerialization isValidJSONObject:obj]) {
NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:kNilOptions error:nil];
NSLog(@"%@----%@",obj,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"该数据不支持转换为JSON");
}
}
5 写数据
目的 : 将plist文件转为JSON格式
相关代码 :
#pragma mark - 写数据
- (void)plistToJson
{
//读取plist文件
NSArray *arrayM = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
//oc
NSData *data = [NSJSONSerialization dataWithJSONObject:arrayM options:kNilOptions error:nil];
//将Json文件写入另外一个文件中
[data writeToFile:@"/Users/xiaofeng/Desktop/apps2.JSON" atomically:YES];
}
三 复杂的JSON解析
案例的大致功能图:

涉及到知识点:
1> JSON解析
2> 利用MJExtension框架实现模型中属性的替换
3> 利用SDWebImage布局cell中的子控件
4> 回到主线程刷新UI
5> 拼接视频下载的完整路径
1 根据提供的相应的接口,下载好的JSON数据
/*
{"videos":[{"id":1,"image":"resources/images/minion_01.png","length":10,"name":"小黄人 第01部","url":"resources/videos/minion_01.mp4"},{"id":2,"image":"resources/images/minion_02.png","length":12,"name":"小黄人 第02部","url":"resources/videos/minion_02.mp4"},{"id":3,"image":"resources/images/minion_03.png","length":14,"name":"小黄人 第03部","url":"resources/videos/minion_03.mp4"},{"id":4,"image":"resources/images/minion_04.png","length":16,"name":"小黄人 第04部","url":"resources/videos/minion_04.mp4"},{"id":5,"image":"resources/images/minion_05.png","length":18,"name":"小黄人 第05部","url":"resources/videos/minion_05.mp4"},{"id":6,"image":"resources/images/minion_06.png","length":20,"name":"小黄人 第06部","url":"resources/videos/minion_06.mp4"}]
*/
注意: 从下载的JSON数据不难看出文件的类型是由字典组成的,JSON里面找一组字典作为写在模型中的属性模型中的属性代码.
代码 :
@property (nonatomic, strong) NSString *image;
@property (nonatomic, assign) NSString *length;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, strong) NSString *ID;
2 由于在提供的JSON属性中出现了id类型,有点和系统中的id一样,看起来别扭,其实将id作为属性写入写没什么问题.但是我们为了改善这点,就用MJ的一个框架来转化.
[XFVidoeItem mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id",
};
}];
3 发送请求的步骤:
3.1> 确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"];
3.2> 创建可变的请求对象
//创建可变的请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
3.3> 设置会话
//设置会话
NSURLSession *session = [NSURLSession sharedSession];
3.4> 创建task任务–>解析JSON文件—->用mj创建模型并且存入数组中—->回到主线程刷新UI
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary *dictM = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
self.videos = [XFVidoeItem mj_objectArrayWithKeyValuesArray:dictM[@"videos"]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
3.5> 开始执行任务
[dataTask resume];
4 自定义cell—>重写系统布局子控件的方法
- (void)layoutSubviews {
[super layoutSubviews]
self.imageView.frame = CGRectMake(5,5,80,40)
float limgW = self.imageView.image.size.width
if(limgW > 0) {
self.textLabel.frame = CGRectMake(90,self.textLabel.frame.origin.y,self.textLabel.frame.size.width,self.textLabel.frame.size.height)
self.detailTextLabel.frame = CGRectMake(90,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width,self.detailTextLabel.frame.size.height)
}
}
5 tableView的数据源方法(只标上重点部分)
#pragma mark - 每行cell的内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
XFVidoeCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
XFVidoeItem *vidoeItem = self.videos[indexPath.row];
cell.textLabel.text = vidoeItem.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"播放时间:%@秒",vidoeItem.length];
NSURL *url = [NSURL URLWithString:[BaseURL stringByAppendingPathComponent:vidoeItem.image]];
[cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160320_2.png"]];
return cell;
}
6 注意由于提供的视频的下载只有响应体部分,还有接口部分省略了,那么由于是下载视频是模型中的url,所以需要我们自己拼接.
7 用户点击某行cell,播放出相应的视频
#pragma mark - 点击某行cell播放视频
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
XFVidoeItem *vidoeItem = self.videos[indexPath.row];
NSString *urlStr = [BaseURL stringByAppendingPathComponent:vidoeItem.url];
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:urlStr]];
[self presentViewController:vc animated:YES completion:nil];
}
四 复杂的XML解析数据方法一
1 大部分方法和普通的JSON解析数据是一样的,只需要将JSON部分的代码改为XML解析的代码就可以,主要修改创建task任务的部分代码.
[XFVidoeItem mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id",
};
}];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[dataTask resume];
}
2 与JSON解析不同的部分是在XML解析数据是在代理方法中完成解析的,下面是数据解析的代码部分
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict
{
NSLog(@"%s---开始解析元素%@----\n%@",__func__,elementName,attributeDict);
if ([elementName isEqualToString:@"videos"]) {
return;
}
XFVidoeItem *item = [[XFVidoeItem alloc] init];
[item mj_setKeyValues:attributeDict];
[self.videos addObject:item];
}
注意部分: 会不会出现当XML还没有解析完毕,就开始刷新tableView呢?不会,因为调用代理的那个方法本身是阻塞的,需要在XML都解析完毕,才会刷新.
五 复杂的XML解析数据方法二—>用GDataXML框架解析(基本没人用)
1 导入头文件GDataXMLNode.h
2 在创建task任务的方法中写入下面代码就可以完成用框架对XML的解析
//加载整个XML文件
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil]
//拿到根元素,得到根元素内部所有为video的属性
NSArray *eles = [doc.rootElement elementsForName:@"video"]
//遍历所有的子元素
for (GDataXMLElement *ele in eles) {
//创建一个模型,给模型中的属性赋值
XFVidoeItem *item = [[XFVidoeItem alloc] init]
//给属性赋值
item.name = [ele attributeForName:@"name"].stringValue
item.image = [ele attributeForName:@"image"].stringValue
item.ID = [ele attributeForName:@"id"].stringValue
item.length = [ele attributeForName:@"length"].stringValue
item.url = [ele attributeForName:@"url"].stringValue
//将赋值好的模型加入到装模型的可变数组中
[self.videos addObject:item]
}
3 配置Xcode,因为如果就写上上面的代码部分,运行起来是会报错的,所以需要配置xcode,在开发的时候一般都是用苹果提供的类来解析XML,下面是xcode配置信息.只要将图片上的地方配置好了,也是能达到解析XML的目的.
图一:

图二:

图三:

4 需要填写的信息来源地:
图一:

图二:

六 结尾
1 以上就是JSON和XML解析的部分解释和代码,或许不完全.这里要重申一次,一般在开发当中,从服务器返回的数据一般都是JSON数据,所以还是需要重点掌握以下.但是XML解析也是需要知道的,这里面有什么不足的地方,希望大家给我留言,谢谢!!!!