JSON 解析常用的第三方架構有:JSONKit、SBJson、TouchJSON,其性從左至右依次降低。但是從IOS5開始,APPLE提供了對json的原生支援(NSJSONSerialization)。
JSONKit 已經在 2012 年停止更新,官方說 JSONKit 比蘋果原生的 NSJSONSerialization 解析速度快,實測其實蘋果原生的 NSJSONSerialization 解析速度更快。
本文就只介紹ios原生的NSJSONSerialization和常用的JSONKit: 1、系統方式 JSON 資料解析
解析 json 資料
/* 還原序列化:將從伺服器接收到的位元據轉換成 NSDictionary / NSArray 的過程,簡化程式開發,便於後續的字典轉模型。 資料必須符合 json 格式,用來接收的容器必須和 json 的最外層保持一致。 NSJSONReadingMutableContainers = (1UL << 0), // 容器可變,NSMutableDictionary 或 NSMutableArray。 NSJSONReadingMutableLeaves = (1UL << 1), // 葉子可變,返回的 JSON 對象中字串的值為 NSMutableString。 NSJSONReadingAllowFragments = (1UL << 2) // 允許 JSON 字串最外層既不是 NSArray 也不是 NSDictionary, 但必須是有效 JSON 片段 還原序列化中的可變不可變,實際用處不大,後續緊接著就是字典轉模型。因此輸入 0 效率最好。如果今後看到 ** 類型的參數, 又不想擷取對應的內容,傳遞 NULL 即可。傳入 nil 不會抱錯。 */ // 從本地檔案中讀取資料 NSData *jsonData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"JsonDataFile" ofType:@"txt"]]; // 解析 json 資料 id result = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:NULL];
產生 json 資料:
/* 序列化:將字典或者數組發送給伺服器之前,轉換成位元據,方便網路傳輸。 產生 json 資料的對象必須滿足以下條件: 對象最外層必須是 NSArray 或者 NSDictionary。 容器內的所有資料必須是 NSString, NSNumber, NSArray, NSDictionary, 或者 NSNull 類型。 字典的所有 key 都是 NSString 格式。 NSNumber 不能是 NaN(非數值) 或者 infinity(無限大)。 NSJSONWritingOptions: NSJSONWritingPrettyPrinted = (1UL << 0) 漂亮的格式列印 使用 0 時,產生的資料格式如下,將 JSON 資料發送給伺服器時可以使用該種格式。 {"age":8,"score":99,"add":"beijing","name":"xiaoxin"} 使用 1 時,產生的資料格式如下,將 JSON 資料儲存到本地時可以使用該種格式。 { "age" : 8, "score" : 99, "add" : "beijing", "name" : "xiaoxin" } */ // Foundation object NSDictionary *dicitionary = @{@"name":@"xiaoxin", @"age":@8, @"score":@99, @"add":@"beijing"}; // 判斷 Foundation 對象是否可以產生 json 資料 BOOL isValid = [NSJSONSerialization isValidJSONObject:dicitionary]; // 產生 json 資料 NSData *jData = [NSJSONSerialization dataWithJSONObject:dicitionary options:0 error:NULL];
2.JSONKit 方式 JSON 資料解析
SONDecoder 方式解析
// 從本地檔案中讀取資料 NSData *jsonData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"JsonDataFile" ofType:@"txt"]]; id result = [[JSONDecoder decoder] objectWithData:jsonData]; NSLog(@"%@ %@", result, [result class]);
JSONString 解析
// 單層 JSONString 解析 /* 如果 json 是 “單層” 的,即 value 都是字串、數字,可以使用 objectFromJSONString */ // 單層 JSONString 資料 NSString *jsonStr1 = @"{\"a\":123, \"b\":\"abc\"}"; // 返回可變結果使用 mutableObjectFromJSONString 方法 NSDictionary *jsonStrDic1 = [jsonStr1 objectFromJSONString]; // 嵌套 JSONString 解析 /* 如果 json 有嵌套,即 value 裡有 array、object,如果再使用 objectFromJSONString,程式可能會報錯, 測試結果表明:使用由網路或得到的 php/json_encode 產生的 json 時會報錯,但使用 NSString 定義的 json 字串時, 解析成功,最好使用 objectFromJSONStringWithParseOptions: */ // 嵌套 JSONString 資料 NSString *jsonStr2 = @"{\"a\":123, \"b\":\"abc\", \"c\":[456, \"hello\"], \"d\":{\"name\":\"張三\", \"age\":\"32\"}}"; // 返回可變結果使用 mutableObjectFromJSONStringWithParseOptions 方法 NSDictionary *jsonStrDic2 = [jsonStr2 objectFromJSONStringWithParseOptions:JKParseOptionLooseUnicode];
產生 JSONString 資料
// NSString -> JSONString NSString *str1 = @"{a\":123, \"b\":\"abc\"}"; // 預設參數為 JKSerializeOptionNone,includeQuotes 為 YES NSString *jsonStrFromStr1 = [str1 JSONString]; // includeQuotes 為 NO 時,編碼後的資料最外層不含引號 NSString *jsonStrFromStr2 = [str1 JSONStringWithOptions:JKSerializeOptionNone includeQuotes:NO error:nil]; // NSArray/NSDictionary -> JSONString NSDictionary *dic1 = @{@"name":@"xiaoxin", @"age":@8, @"Info":@{@"score":@99, @"add":@"beijing"}}; // 預設參數為 JKSerializeOptionNone NSString *jsonStrFromDic1 = [dic1 JSONString]; NSString *jsonStrFromDic2 = [dic1 JSONStringWithOptions:JKSerializeOptionEscapeUnicode error:nil];
JSONData 解析
// 單層 JSONData 解析 NSData *jsonData1 = [@"{\"a\":123, \"b\":\"abc\"}" dataUsingEncoding:NSUTF8StringEncoding]; // 返回可變結果使用 mutableObjectFromJSONData 方法 NSDictionary *jsonDataDic1 = [jsonData1 objectFromJSONData]; // 嵌套 JSONData 解析 // 從本地檔案中讀取資料 NSData *jsonData2 = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"JsonDataFile" ofType:@"txt"]]; // 返回可變結果使用 mutableObjectFromJSONStringWithParseOptions 方法 NSDictionary *jsonDataDic2 = [jsonData2 objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode];
產生 JSONData 資料
// NSString -> JSONData NSString *str2 = @"{a\":123, \"b\":\"abc\"}"; // 預設參數為 JKSerializeOptionNone,includeQuotes 為 YES NSData *jsonDataFromStr1 = [str2 JSONData]; NSData *jsonDataFromStr2 = [str2 JSONDataWithOptions:JKSerializeOptionNone includeQuotes:NO error:nil]; // NSArray/NSDictionary -> JSONData NSDictionary *dic2 = @{@"name":@"xiaoxin", @"age":@8, @"Info":@{@"score":@99, @"add":@"beijing"}}; // 預設參數為 JKSerializeOptionNone NSData *jsonDataFromDic1 = [dic2 JSONData]; NSData *jsonDataFromDic2 = [dic2 JSONDataWithOptions:JKSerializeOptionEscapeUnicode error:nil];
補充:
利用字典NSDictionary轉換為鍵/值格式的資料。
// 如果數組或者字典中儲存了 NSString, NSNumber, NSArray, NSDictionary, or NSNull 之外的其他對象,就不能直接儲存成檔案了.也不能序列化成 JSON 資料. NSDictionary *dict = @{@"name" : @"me", @"do" : @"something", @"with" : @"her", @"address" : @"home"}; // 1.判斷當前對象是否能夠轉換成JSON資料. // YES if obj can be converted to JSON data, otherwise NO BOOL isYes = [NSJSONSerialization isValidJSONObject:dict]; if (isYes) { NSLog(@"可以轉換"); /* JSON data for obj, or nil if an internal error occurs. The resulting data is a encoded in UTF-8. */ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:NULL]; /* Writes the bytes in the receiver to the file specified by a given path. YES if the operation succeeds, otherwise NO */ // 將JSON資料寫成檔案 // 檔案添加尾碼名: 告訴別人當前檔案的類型. // 注意: AFN是通過檔案類型來確定資料類型的!如果不添加類型,有可能識別不了! 自己最好添加檔案類型. [jsonData writeToFile:@"/Users/SunnyBoy/Sites/JSON_XML/dict.json" atomically:YES]; NSLog(@"%@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]); } else { NSLog(@"JSON資料產生失敗,請檢查資料格式"); }
通過JSON序列化可以轉換數組,但轉換結果不是標準化的JSON格式。
NSArray *array = @[@"qn", @18, @"ya", @"wj"]; BOOL isYes = [NSJSONSerialization isValidJSONObject:array]; if (isYes) { NSLog(@"可以轉換"); NSData *data = [NSJSONSerialization dataWithJSONObject:array options:0 error:NULL]; [data writeToFile:@"/Users/SunnyBoy/Sites/JSON_XML/base" atomically:YES]; } else { NSLog(@"JSON資料產生失敗,請檢查資料格式"); }