JSON數(shù)據(jù)解析:
- JSON的簡(jiǎn)單介紹:
- 什么是JSON
- JSON以一種輕量級(jí)的數(shù)據(jù)格式,一般用來數(shù)據(jù)交互
- 服務(wù)器返回給客戶端的數(shù)據(jù)一般都是JSON或者XML格式(問價(jià)下載除外)
- JSON相關(guān)說明
- JSON格式很想oc中的字典
- 標(biāo)準(zhǔn)JSON格式中的key必須是雙引號(hào)
- 解析JSON的方案
- 第三方框架
- 蘋果原生:NSJSONSerialization
- JSON解析相關(guān)代碼
- JSON數(shù)據(jù)->OC(反序列化)
//把json數(shù)據(jù)轉(zhuǎn)換為OC對(duì)象
-(void)jsonToOC
{
//1. 確定url路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=33&pwd=33&type=JSON"];
//2.創(chuàng)建一個(gè)請(qǐng)求對(duì)象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.使用NSURLSession發(fā)送一個(gè)異步請(qǐng)求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.當(dāng)接收到服務(wù)器響應(yīng)的數(shù)據(jù)后,解析數(shù)據(jù)(JSON--->OC)
/*
第一個(gè)參數(shù):要解析的JSON數(shù)據(jù),是NSData類型也就是二進(jìn)制數(shù)據(jù)
第二個(gè)參數(shù): 解析JSON的可選配置參數(shù)
NSJSONReadingMutableContainers 解析出來的字典和數(shù)組是可變的
NSJSONReadingMutableLeaves 解析出來的對(duì)象中的字符串是可變的 iOS7以后有問題
NSJSONReadingAllowFragments 被解析的JSON數(shù)據(jù)如果既不是字典也不是數(shù)組, 那么就必須使用這個(gè)
*/
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@",dict);
}];
}
//1.要轉(zhuǎn)換成JSON數(shù)據(jù)的OC對(duì)象*這里是一個(gè)字典
NSDictionary *dictM = @{
@"name":@"wendingding",
@"age":@100,
@"height":@1.72
};
//2.OC->JSON
/*
注意:可以通過+ (BOOL)isValidJSONObject:(id)obj;方法判斷當(dāng)前OC對(duì)象能否轉(zhuǎn)換為JSON數(shù)據(jù)
具體限制:
1.obj 是NSArray 或 NSDictionay 以及他們派生出來的子類
2.obj 包含的所有對(duì)象是NSString,NSNumber,NSArray,NSDictionary 或NSNull
3.字典中所有的key必須是NSString類型的
4.NSNumber的對(duì)象不能是NaN或無窮大
*/
/*
第一個(gè)參數(shù):要轉(zhuǎn)換成JSON數(shù)據(jù)的OC對(duì)象,這里為一個(gè)字典
第二個(gè)參數(shù):NSJSONWritingPrettyPrinted對(duì)轉(zhuǎn)換之后的JSON對(duì)象進(jìn)行排版,無意義
*/
NSData *data = [NSJSONSerialization dataWithJSONObject:dictM options:NSJSONWritingPrettyPrinted error:nil];
//3.打印查看Data是否有值
/*
第一個(gè)參數(shù):要轉(zhuǎn)換為STring的二進(jìn)制數(shù)據(jù)
第二個(gè)參數(shù):編碼方式,通常采用NSUTF8StringEncoding
*/
NSString *strM = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",strM);
- OC對(duì)象與JSON對(duì)象之間的一一對(duì)應(yīng)關(guān)系
//OC對(duì)象和JSON數(shù)據(jù)之間的一一對(duì)應(yīng)關(guān)系
-(void)oCWithJSON
{
//JSON的各種數(shù)據(jù)格式
//NSString *test = @"\"wendingding\"";
//NSString *test = @"true";
NSString *test = @"{\"name\":\"wendingding\"}";
//把JSON數(shù)據(jù)->OC對(duì)象,以便查看他們之間的一一對(duì)應(yīng)關(guān)系
//注意點(diǎn):如何被解析的JSON數(shù)據(jù)如果既不是字典也不是數(shù)組(比如是NSString), 那么就必須使用這NSJSONReadingAllowFragments
id obj = [NSJSONSerialization JSONObjectWithData:[test dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", [obj class]);
/* JSON數(shù)據(jù)格式和OC對(duì)象的一一對(duì)應(yīng)關(guān)系
{} -> 字典
[] -> 數(shù)組
"" -> 字符串
10/10.1 -> NSNumber
true/false -> NSNumber
null -> NSNull
*/
}
}
- 如何查看復(fù)雜的JSON數(shù)據(jù)
```objc
[dictM writeToFile:@"/Users/文頂頂/Desktop/videos.plist" atomically:YES];
```
- 視頻的簡(jiǎn)單播放
//0.需要導(dǎo)入系統(tǒng)框架
#import <MediaPlayer/MediaPlayer.h>
//1.拿到該cell對(duì)應(yīng)的數(shù)據(jù)字典
XMGVideo *video = self.videos[indexPath.row];
NSString *videoStr = [@"http://120.25.226.186:32812" stringByAppendingPathComponent:video.url];
//2.創(chuàng)建一個(gè)視頻播放器
MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString:videoStr]];
//3.present播放控制器
[self presentViewController:vc animated:YES completion:nil];
- MJExtension
- 簡(jiǎn)單使用
```objc
//1.把字典數(shù)組轉(zhuǎn)換為模型數(shù)組
//使用MJExtension框架進(jìn)行字典轉(zhuǎn)模型
self.videos = [XMGVideo mj_objectArrayWithKeyValuesArray:videoArray];
//2.重命名模型屬性的名稱
//第一種重命名屬性名稱的方法,有一定的代碼侵入性
//設(shè)置字典中的id被模型中的ID替換
+(NSDictionary *)mj_replacedKeyFromPropertyName
{
return @{
@"ID":@"id"
};
}
//第二種重命名屬性名稱的方法,代碼侵入性為零
[XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id"
};
}];
//3.MJExtension框架內(nèi)部實(shí)現(xiàn)原理-運(yùn)行時(shí)
```
XML解析
//1.發(fā)送請(qǐng)求
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//2.解析數(shù)據(jù)
//2.1 創(chuàng)建XML解析器
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
//2.2 設(shè)置代理
parser.delegate = self;
//2.3 開始解析,該方法本身是阻塞的
[parser parse];
//4.刷新tableView
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}] resume];
//1.開始解析XML文檔
-(void)parserDidStartDocument:(nonnull NSXMLParser *)parser
//2.開始解析XML中某個(gè)元素的時(shí)候調(diào)用,比如<video>
-(void)parser:(nonnull NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict
{
if ([elementName isEqualToString:@"videos"]) {
return;
}
//字典轉(zhuǎn)模型
XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict];
[self.videos addObject:video];
}
//3.當(dāng)某個(gè)元素解析完成之后調(diào)用,比如</video>
-(void)parser:(nonnull NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName
//4.XML文檔解析結(jié)束
-(void)parserDidEndDocument:(nonnull NSXMLParser *)parser
```objc
//0.告訴框架新值和舊值的對(duì)應(yīng)關(guān)系
[XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id",
};
}];
```
- NSURLSessionDownloadTask大文件下載
- NSURLSessionDownloadTask實(shí)現(xiàn)大文件下載-Block
- 使用URLSession和URLSessionDownload可以很方便的實(shí)現(xiàn)文件下載
```objc
1)使用NSURLSession和NSURLSessionDownload可以很方便的實(shí)現(xiàn)文件下載操作
/*
第一個(gè)參數(shù):要下載文件的url路徑
第二個(gè)參數(shù):當(dāng)接收完服務(wù)器返回的數(shù)據(jù)之后調(diào)用該block
location:下載的文件的保存地址(默認(rèn)是存儲(chǔ)在沙盒中tmp文件夾下面,隨時(shí)會(huì)被刪除)
response:服務(wù)器響應(yīng)信息,響應(yīng)頭
error:該請(qǐng)求的錯(cuò)誤信息
*/
//說明:downloadTaskWithURL方法已經(jīng)實(shí)現(xiàn)了在下載文件數(shù)據(jù)的過程中邊下載文件數(shù)據(jù),邊寫入到沙盒文件的操作
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * __nullable location, NSURLResponse * __nullable response, NSError * __nullable error)
```
- downloadTaskWithURL內(nèi)部已經(jīng)實(shí)現(xiàn)了邊下載邊寫入操作,所以開發(fā)人員不必?fù)?dān)心內(nèi)存問題
- 文件下載后默認(rèn)保存到tmp目錄,需要手動(dòng)剪切到指定的沙盒目錄
- 缺點(diǎn):無法監(jiān)聽下載進(jìn)度
- 使用NSURLSessionDownloadTask實(shí)現(xiàn)大文件下載-代理
- 創(chuàng)建NSURLSession并設(shè)置代理,通過NSURLSessionDownloadTask并以代理的方式實(shí)現(xiàn)大文件的下載
//1.創(chuàng)建NSULRSession,設(shè)置代理
self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//2.創(chuàng)建task
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
self.downloadTask = [self.session downloadTaskWithURL:url];
//3.執(zhí)行task
[self.downloadTask resume];
- 常用代理方法說明
```objc
/*
1.當(dāng)接收到下載數(shù)據(jù)的時(shí)候調(diào)用,可以在該方法中監(jiān)聽文件下載的進(jìn)度
該方法會(huì)被調(diào)用多次
totalBytesWritten:已經(jīng)寫入到文件中的數(shù)據(jù)大小
totalBytesExpectedToWrite:目前文件的總大小
bytesWritten:本次下載的文件數(shù)據(jù)大小
*/
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
/*
2.恢復(fù)下載的時(shí)候調(diào)用該方法
fileOffset:恢復(fù)之后,要從文件的什么地方開發(fā)下載
expectedTotalBytes:該文件數(shù)據(jù)的總大小
*/
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
/*
3.下載完成之后調(diào)用該方法
*/
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location
/*
4.請(qǐng)求完成之后調(diào)用
如果請(qǐng)求失敗,那么error有值
*/
-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
```
- 實(shí)現(xiàn)斷點(diǎn)下載相關(guān)代碼:
```objc
//如果任務(wù),取消了那么以后就不能恢復(fù)了
// [self.downloadTask cancel];
//如果采取這種方式來取消任務(wù),那么該方法會(huì)通過resumeData保存當(dāng)前文件的下載信息
//只要有了這份信息,以后就可以通過這些信息來恢復(fù)下載
[self.downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
self.resumeData = resumeData;
}];
-----------
//繼續(xù)下載
//首先通過之前保存的resumeData信息,創(chuàng)建一個(gè)下載任務(wù)
self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
[self.downloadTask resume];
```
- 計(jì)算當(dāng)前下載進(jìn)度
```objc
//獲取文件下載進(jìn)度
self.progress.progress = 1.0 * totalBytesWritten/totalBytesExpectedToWrite;
```
- 局限性:
```objc
01 如果用戶點(diǎn)擊暫停之后退出程序,那么需要把恢復(fù)下載的數(shù)據(jù)寫一份到沙盒,代碼復(fù)雜度更
02 如果用戶在下載中途未保存恢復(fù)下載數(shù)據(jù)即退出程序,則不具備可操作性
```
- NSURLSessionDataTask實(shí)現(xiàn)大文件下載:
- 關(guān)于NSOutputStream的使用
//1. 創(chuàng)建一個(gè)輸入流,數(shù)據(jù)追加到文件的屁股上
//把數(shù)據(jù)寫入到指定的文件地址,如果當(dāng)前文件不存在,則會(huì)自動(dòng)創(chuàng)建
NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];
//2. 打開流
[stream open];
//3. 寫入流數(shù)據(jù)
[stream write:data.bytes maxLength:data.length];
//4.當(dāng)不需要的時(shí)候應(yīng)該關(guān)閉流
[stream close];
- 關(guān)于網(wǎng)絡(luò)請(qǐng)求頭的設(shè)置(可以設(shè)置指定下載某一部分文件)
//1. 設(shè)置請(qǐng)求對(duì)象
//1.1 創(chuàng)建請(qǐng)求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
//1.2 創(chuàng)建可變請(qǐng)求對(duì)象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//1.3 拿到當(dāng)前文件的殘留數(shù)據(jù)大小
self.currentContentLength = [self FileSize];
//1.4 告訴服務(wù)器從哪個(gè)地方開始下載文件數(shù)據(jù)
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];
NSLog(@"%@",range);
//1.5 設(shè)置請(qǐng)求頭
[request setValue:range forHTTPHeaderField:@"Range"];
文件的壓縮與解壓縮
多值參數(shù)和中文輸出
- 多值參數(shù)
/*
如果一個(gè)參數(shù)對(duì)應(yīng)著多個(gè)值,那么直接按照"參數(shù)=值&參數(shù)=值"的方式拼接
*/
-(void)test
{
//1.確定URL
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/weather?place=Beijing&place=Guangzhou"];
//2.創(chuàng)建請(qǐng)求對(duì)象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.發(fā)送請(qǐng)求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.解析
NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
}
- 如何解決字典或者數(shù)組輸出亂碼的問題
給字典和數(shù)組添加一個(gè)分類,重寫descriptionWithLocale方法,在該方法中拼接元素格式化輸出。
-(nonnull NSString *)descriptionWithLocale:(nullable id)locale
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。