在iOS開發中,涉及到從網絡取得json格式的數據處理工作時,我們會想到很多開源的第三方包,如SBJSON。在iOS5開始,也增加了對json格式數據的處理能力,增加的類是NSJSONSerialization。
使用NSJSONSerialization,可以分析各種復雜格式json數據。
使用的類方法是+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error。
根據不同data的結構,設置不同的option。這裡option有三類:NSJSONReadingMutableContainers, NSJSONReadingMutableLeaves , NSJSONReadingAllowFragments。
apple文檔對這三種方法做了說明。
1、NSJSONReadingMutableContainers
Specifies that arrays and dictionaries are created as mutable objects.
2、NSJSONReadingMutableLeaves
Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString.
3、NSJSONReadingAllowFragments
Specifies that the parser should allow top-level objects that are not an instance of NSArray or NSDictionary.
Available in iOS 5.0 and later.
我就www.2cto.com這個鏈接做了測試。這是google的地理信息api,根據地點得到經緯度等信息。
這個url得到的json格式的結果如下所示:
[javascript]
{
"results" : [
{
"address_components" : [
{
"long_name" : "南京",
"short_name" : "南京",
"types" : [ "locality", "political" ]
},
{
"long_name" : "江蘇省",
"short_name" : "江蘇省",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "中國",
"short_name" : "CN",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "中國江蘇省南京市",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 32.61436330,
"lng" : 119.23624250
},
"southwest" : {
"lat" : 31.22809770,
"lng" : 118.36337310
}
},
"location" : {
"lat" : 32.0602550,
"lng" : 118.7968770
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 32.39401350,
"lng" : 119.0501690
},
"southwest" : {
"lat" : 31.80452470,
"lng" : 118.42533230
}
}
},
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}
這是一個復雜的json格式,json中包含了數組,數組中有包含了若干級的json數據。
先將URL轉碼為UTF8,基於它創建一個NSMutableURLRequest,再使用NSURLConnection的sendAsynchronousRequest的方法,將response數據放到block中分析,分析方法就是NSJSONSerialization的類方法+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error。
它的分析步驟如下:
第一步,根據json數據結構得到字典
NSDictionary *resultsDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
第二步,根據字典中組成,得到key為@"results"對應的對象是數組。
NSArray *resultsArr = [resultsDic objectForKey:@"results"];
第三步,使用for循環遍歷這個數組
for (NSDictionary * resultDetailDic in resultsArr)
{
NSDictionary * locationDic=[[resultDetailDic objectForKey:@"geometry"] objectForKey:@"location"];
NSString * lat=[locationDic objectForKey:@"lat"];
NSString * lng=[locationDic objectForKey:@"lng"];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"locationDic.lat 是--->%@\n",lat);
NSLog(@"locationDic.lng 是--->%@\n",lng);
});// dispatch async main
}
第四步,根據for循環遍歷的結果,得到每一個元素都是一個字典。
NSDictionary * locationDic=[[resultDetailDic objectForKey:@"geometry"] objectForKey:@"location"];
第五步,根據字典信息,得到每一個key對應的對象是一個字符串
這個字符串就是我們最終要的數據。
如果覺得這種數據分析對數據結構關聯太密切,謂之曰不夠強壯,你可以做一些isKindOfClass判斷。
全部代碼如下:
[cpp]
-(void)parseJson:(NSString *)addr
{
//The URL of JSON service
NSString *_urlString = @"http://maps.googleapis.com/maps/api/geocode/json?address=nanjing&sensor=true";
NSString *_dataString = [[NSString alloc] initWithData:[_urlString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES] encoding:NSASCIIStringEncoding];
//_dataString=[NSString stringWithUTF8String:[_urlString UTF8String]];
NSURL *_url = [NSURL URLWithString:_dataString];
NSMutableURLRequest *_request = [NSMutableURLRequest requestWithURL:_url];
[_request setValue:@"accept" forHTTPHeaderField:@"application/json"];
[NSURLConnection sendAsynchronousRequest:_request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse* response, NSData* data, NSError* error) {
//block define statment
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int responseStatusCode = [httpResponse statusCode];
NSLog(@"response status code is %d",responseStatusCode);
NSError *_errorJson = nil;
NSDictionary *resultsDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (_errorJson != nil) {
NSLog(@"Error %@", [_errorJson localizedDescription]);
} else {
NSString *resultStatus = [resultsDic objectForKey:@"status"];
if ([resultStatus isEqualString:@"OK"])
{
NSArray *resultsArr = [resultsDic objectForKey:@"results"];
//Do something with returned array
for (NSDictionary * resultDetailDic in resultsArr)
{
NSDictionary * locationDic=[[resultDetailDic objectForKey:@"geometry"] objectForKey:@"location"];
NSString * lat=[locationDic objectForKey:@"lat"];
NSString * lng=[locationDic objectForKey:@"lng"];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"locationDic.lat 是--->%@\n",lat);
NSLog(@"locationDic.lng 是--->%@\n",lng);
});// dispatch async main
}
}
}
}];
}
通過這段代碼,我們可以實現異步讀取,json格式數據分析。這些操作都不需要調用任何第三方代碼,僅僅使用了apple自身提供的功能。這樣做的好處,便於維護和升級。