前言:對服務器請求之後,返回給客戶端的數據,一般都是JSON格式或者XML格式(文件下載除外)


本篇隨便先講解JSON解析。
正文:
關於JSON:
JSON是一種輕量級的數據格式,一般用於數據交互JSON的格式很像Objective-C中的字典和數組:{"name":"jack","age":10}
補充:
標准的JSON格式的注意點:key必須用雙引號。(但是在Java中是單引號)
JSON-OC的轉換對照表

其中:null--返回OC裡的NSNull類型
使用:
在JSON解析方案有很多種,但是(蘋果原生的)NSJSONSerialization性能最好
反序列化(JSON --> OC對象),下面示例解析成字典對象

序列化(OC對象 --> JSON),注意字典的值不能傳nil,但是可以傳[NSNull null]

並不是所有的類型都是可以轉為JSON的
以下是蘋果官方規定:

我們再來看個實例:
#import "MainViewController.h"
#import "Video.h"
#define kBaseURL @"http://192.168.3.252/~apple"
@interface MainViewController ()
@property (strong, nonatomic) NSArray *dataList;
@property (weak, nonatomic) UITableView *tableView;
@end
@implementation MainViewController
class="p1">
"412158" snippet_file_name="blog_20140630_1_3481337" name="code" class="objc">
#pragma mark 實例化視圖
- (void)loadView
{
self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
//1 tableview
CGRect frame = self.view.bounds;
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height - 44) style:UITableViewStylePlain];
//1)數據源
[tableView setDataSource:self];
//2)代理
[tableView setDelegate:self];
//)設置表格高度
[tableView setRowHeight:80];
[self.view addSubview:tableView];
self.tableView = tableView;
//toolBar
UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, tableView.bounds.size.height, 320, 44)];
[self.view addSubview:toolBar];
//添加toolbar按鈕
UIBarButtonItem *item1 = [[UIBarButtonItem alloc]initWithTitle:@"load json" style:UIBarButtonItemStyleDone target:self action:@selector(loadJson)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc]initWithTitle:@"load xml" style:UIBarButtonItemStyleDone target:self action:@selector(loadXML)];
UIBarButtonItem *item3 = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[toolBar setItems:@[item3, item1, item3, item2, item3]];
}
#pragma mark -uitableview數據源方法 對於uitableview下面這兩個方法是必須實現的。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataList.count;
}
//每填充一行都調用一次這個方法。知道界面上的所有行都填充完畢。,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//使用可充用標示符查詢可重用單元格
static NSString *ID = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
//設置單元格內容
Video *v = self.dataList[indexPath.row];
cell.textLabel.text = v.name;
cell.detailTextLabel.text = v.teacher;
//加載圖片
//1)同步加載網絡圖片,同步方法以為這這些指令在完成之前,後續指令都無法執行。
//注意:在開發網絡應用時,不要使用同步方法加載圖片,否則會嚴重影響用戶體驗
// NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL];
// NSURL *imageUrl = [NSURL URLWithString:imagePath];
// NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
// UIImage *image = [UIImage imageWithData:imageData];
//
// //2)異步加載網絡圖片
// //網絡連接本身就有異步命令 sendAsync
// [cell.imageView setImage:image];
//如果緩存圖像不存在
if (v.cacheImage == nil) {
//使用默認圖像占位,即能夠保證有圖像,又能夠保證有地方。
UIImage *image = [UIImage imageNamed:@"user_default.png"];
[cell.imageView setImage:image]; //使用默認圖像占位
//開啟異步連接,加載圖像,因為加載完成之後,需要刷新對應的表格航
[self loadImageAsyncWithIndexPath:indexPath];
}else
{
[cell.imageView setImage:v.cacheImage];
}
//[self loadImageAsyncWithUrl:imageUrl imageView:cell.imageView];
return cell;
}
#pragma mark 異步加載網絡圖片
//由於uitableview是可重用的,為了避免用戶快速頻繁刷新表格,造成數據沖突,不能直接將uiimageview傳入異步方法
//正確的解決方法是:將表格行的indexpath傳入異步方法,加載完成圖像以後,直接刷新指定的行。
- (void)loadImageAsyncWithIndexPath:(NSIndexPath *)indexPath
{
Video *v = self.dataList[indexPath.row]; //取出當前要填充的行
NSString *imagePath = [NSString stringWithFormat:@"%@%@", kBaseURL, v.imageURL];
NSURL *imageUrl = [NSURL URLWithString:imagePath];
//NSLog(@"%@ %@", url, imageView);
//1 request
NSURLRequest *request = [NSURLRequest requestWithURL:imageUrl];
//2 connection sendasync異步請求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
//UIImage *image = [UIImage imageWithData:data];
//[imageView setImage:image];
//將網絡數據保存至緩存圖像。
v.cacheImage = [UIImage imageWithData:data];
//刷新表格
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}];
}
#pragma mark 處理json數據
- (void)handlerJSONData:(NSData *)data
{
//json文件中的[]表示一個數據。
//反序列化json數據
//第二個參數是解析方式,一般用NSJSONReadingAllowFragments
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", array); //json解析以後是nsarray格式的數據。
//提示:如果開發網絡應用,可以將反序列化出來的對象,保存至沙箱,以便後續開發使用。
NSArray *docs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [docs[0]stringByAppendingPathComponent:@"json.plist"];
[array writeToFile:path atomically:YES]; //把array裡面的數據寫入沙箱中的jspn.plist中。
//給數據列表賦值
NSMutableArray *arrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
Video *video = [[Video alloc]init];
//給video賦值
[video setValuesForKeysWithDictionary:dict];
[arrayM addObject:video];
}
self.dataList = arrayM;
//刷新表格
[self.tableView reloadData];
NSLog(@"%@", arrayM); //這句話將調用video裡面的description和nsarray+log裡面的descriptionWithLocale
}
#pragma mark 加載json
- (void)loadJson
{
NSLog(@"load json");
//從web服務器加載數據
NSString *str = @"http://www.baidu.com?format=json"; //這裡是亂寫的
//提示:NSData本身具有同步方法,但是在實際開發中,不要使用次方法
//在使用NSData的同步方法時,無法指定超時時間,如果服務器連接不正常,會影響用戶體驗。
//NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
//簡歷NSURL
NSURL *url = [NSURL URLWithString:str];
//建立NSURLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:2.0f];
//建立NSURLConnect的同步方法加載數據
NSURLResponse *response = nil;
NSError *error = nil;
//同步加載數據
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//錯誤處理
if (data != nil) {
//下面這兩句話本身沒有什麼意義,僅用於跟蹤調試。
NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
//在處理網絡數據的時候,不要將NSData轉換成nsstring。
[self handlerJSONData:data];
}else if (data == nil && error == nil){
NSLog(@"空數據");
}else
{
NSLog(@"%@", error.localizedDescription);
}
}
#pragma mark 加載xml
- (void)loadXML
{
NSLog(@"load xml");
}
//- (void)viewDidLoad
//{
// [super viewDidLoad];
//}
@end