JSON数据的解析
什么是JSON
-
JSON是一种轻量级的数据格式,一般用于数据交互
-
服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外)
-
JSON的格式很像OC中的字典和数组
{"name" : "jack", "age" : 10}
{"names" : ["jack", "rose", "jim"]}
** 标准JSON格式的注意点:key必须用双引号 ** -
要想从JSON中挖掘出具体数据,得对JSON进行解析
-
JSON – OC 转换对照表
1.png -
JSON – OC 转换练习
2.png
JSON解析方案
在iOS中,JSON的常见解析方案有4种
- 第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
- 苹果原生(自带):NSJSONSerialization(性能最好)
- NSJSONSerialization的常见方法
- JSON数据转 OC对象
+ (id)JSONObjectWiythData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
- OC对象转 JSON数据
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
解析来自服务器的JSON
3.pngjson数据-> OC对象
-(void)JSONtoOC
{ //1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=23&pwd=2344&type=JSON"];
//2.创建请求对象
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
//3.使用 NSURLSession 发送一个异步请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.当接收到服务器的响应数据后解析数据(json数据————>OC数据)
//将文字读取到字符串中
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
/**把JSON转换为OC对象
第一个参数:要解析的json数据,是NSDate类型也就是二进制数据
第二个参数:可选配置参数
NSJSONReadingMutableContainers:生成的是可变的字典或数组
NSJSONReadingMutableLeaves:内部元素的字符串也是可变的,iOS7以后有问题
NSJSONReadingAllowFragments:如果最外层不是字典或数组那么就必须用这个
kNilOptions:默认
*/
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",dict);
}];
}
OC对象-> son数据
-(void)OCtoJSON
{
// NSDictionary *dict =@{
// @"name":@"xiaomage"
// };
NSString *str = @"xiaomage";
/*
- Top level object is an NSArray or NSDictionary
- All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
- All dictionary keys are NSStrings
- NSNumbers are not NaN or infinity
1.最外层是字典或数组
2.元素必须是 NSString, NSNumber, NSArray, NSDictionary, NSNull
3.所有字典的所有的KEY都必须是NSString
4.NSNumber不能是NAN 或者是无穷大
*/
/* 注意:可以通过`+ (BOOL)isValidJSONObject:(id)obj;`方法判断当前OC对象能否转换为JSON数据
具体限制:
1.obj 是NSArray 或 NSDictionay 以及他们派生出来的子类
2.obj 包含的所有对象是NSString,NSNumber,NSArray,NSDictionary 或NSNull
3.字典中所有的key必须是NSString类型的
4.NSNumber的对象不能是NaN或无穷大
*/
BOOL isValid = [NSJSONSerialization isValidJSONObject:str];
NSLog(@"%d",isValid);
NSData *data = [NSJSONSerialization dataWithJSONObject:str options:kNilOptions error:nil];
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}
-(void)jsonWithOC
{
//模拟JOSN字符串
// NSString *test = @"{\"error\":\"用户名不存在\"}";
// NSString *test = @"[\"a\",\"b\"]";
// NSString *test = @"\"wending\"";
// NSString *test = @"false";
// NSString *test = @"null";
NSString *test = @"10.0";
//把JSON转换成Oc
id obj = [NSJSONSerialization JSONObjectWithData:[test dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",[obj class]);
```
>
JSON数据格式和OC对象的一一对应关系
{} -> 字典
[] -> 数组
"" -> 字符串
10/10.1 -> NSNumber
true/false -> NSNumber
null -> NSNull
/*
json oc
{} @{}
[] @[]
u "" @""
true|false NSNumber
null NSNull == nil
*/
}
----------------------------------------------------------
#(4)如何查看复杂的JSON数据
方法一: 在线格式化http://tool.oschina.net/codeformat/json
方法二: 把解析后的数据写plist文件,通过plist文件可以直观的查看JSON的层次结构。
`[dictM writeToFile:@"/Users/文顶顶/Desktop/videos.plist" atomically:YES];`
@interface ViewController ()
/TableView的数据源/
@property (nonatomic, strong) NSArray *videos;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[XMGVideo setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id"
};
}];
//1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=JSON"];
//2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.发送异步请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.解析数据
NSDictionary *dictM = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// NSLog(@"%@",dictM);
// 将字典写成plist文件,方便查看
[dictM writeToFile:@"/Users/xiaomage/Desktop/video.plist" atomically:YES];
NSArray *arrayM = dictM[@"videos"];
//字典转模型
// NSMutableArray *arr = [NSMutableArray arrayWithCapacity:arrayM.count];
// for (NSDictionary *dict in arrayM) {
// [arr addObject:[XMGVideo videoWithDict:dict]];
// }
//字典数组
self.videos = [XMGVideo objectArrayWithKeyValuesArray:arrayM];
NSLog(@"----%@",self.videos);
//5.刷新TableView
[self.tableView reloadData];
}];
}
pragma mark TableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.videos.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *ID = @"video";
//1.创建cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//拿到该行cell对应的数据
// NSDictionary *videoDict = self.videos[indexPath.row];
XMGVideo *video = self.videos[indexPath.row];
//2.设置cell的数据
/*
cell.textLabel.text = videoDict[@"name"];
NSString *detailStr = [NSString stringWithFormat:@"%@",videoDict[@"length"]];
cell.detailTextLabel.text = detailStr;
NSString *baseUrl = @"http://120.25.226.186:32812/";
NSURL *imageUrl =[NSURL URLWithString:[baseUrl stringByAppendingPathComponent:videoDict[@"image"]]];
[cell.imageView sd_setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:@"123"]];
*/
cell.textLabel.text = video.name;
NSString *detailStr = [NSString stringWithFormat:@"%zd",video.length];
cell.detailTextLabel.text = detailStr;
// 拼接图片URL地址
NSString *baseUrl = @"http://120.25.226.186:32812/";
NSURL *imageUrl =[NSURL URLWithString:[baseUrl stringByAppendingPathComponent:video.image]];
[cell.imageView sd_setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:@"123"]];
NSLog(@"ID---%@",video.ID);
//3.返回cell
return cell;
}
pragma mark---TableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//1.拿到数据
// NSDictionary *videoDict = self.videos[indexPath.row];
XMGVideo *video = self.videos[indexPath.row];
NSString *baseUrl = @"http://120.25.226.186:32812/";
NSURL *mpUrl = [NSURL URLWithString:[baseUrl stringByAppendingPathComponent:video.url]];
// MPMoviePlayerController
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc]initWithContentURL:mpUrl];
[self presentViewController:vc animated:YES completion:nil];
}
#补充:视频的简单播放
1. 需要导入系统框架 #import <MediaPlayer/MediaPlayer.h>
//1.拿到该cell对应的数据字典
XMGVideo *video = self.videos[indexPath.row];
NSString *videoStr = [@"http://120.25.226.186:32812" stringByAppendingPathComponent:video.url];
//2.创建一个视频播放器
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc] initWithContentURL:[NSURL URLWithString:videoStr]];
//3.present播放控制器
[self presentViewController:vc animated:YES completion:nil];
# 字典转模型框架
(1)相关框架
a.Mantle 需要继承自MTModel
b.JSONModel 需要继承自JSONModel
c.MJExtension 不需要继承,无代码侵入性
(2)自己设计和选择框架时需要注意的问题
a.侵入性
b.易用性,是否容易上手
c.扩展性,很容易给这个框架增加新的功能
(3)MJExtension框架的简单使用
//1.把字典数组转换为模型数组
//使用MJExtension框架进行字典转模型
self.videos = [XMGVideo objectArrayWithKeyValuesArray:videoArray];
//2.重命名模型属性的名称
//第一种重命名属性名称的方法,有一定的代码侵入性
//设置字典中的id被模型中的ID替换
+(NSDictionary *)replacedKeyFromPropertyName
{
return @{
@"ID":@"id"
};
}
//第二种重命名属性名称的方法,代码侵入性为零
[XMGVideo setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id"
};
}];
//3.MJExtension框架内部实现原理-运行时