今天和大家一起來學(xué)習(xí)一下iOS序列化和反序列化暑竟,有疏忽的地方,還望各位不吝賜教育勺。
一光羞、序列化和反序列化
序列化: 將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進制串的過程绩鸣。
反序列化:將在序列化過程中所生成的二進制串轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對象的過程。
在iOS中簡單粗暴的解釋
- JSON -> OC 反序列化
- OC -> JSON 序列化
二纱兑、JSON簡介
1呀闻、什么是JSON
- json是一種輕量級的數(shù)據(jù)格式
- 服務(wù)器返回給客戶端的數(shù)據(jù),一般都是json或者xml的數(shù)據(jù)
- 80%都是json
2潜慎、JSON和OC的對應(yīng)關(guān)系
- 標準的JSON的 key 必須使用雙引號 iOS必須是雙引號
- json中的{} 對應(yīng)OC中的NSDictionary
- json中的[] 對應(yīng)OC中的NSArray
- json中的雙引號 對應(yīng)OC中的NSString
- json中的數(shù)字 對應(yīng)OC中的NSNumber
3捡多、JSON的解析方案
- 第三方框架:MJExtension(不需要繼承,代碼沒有侵入性)
在選用框架時注意的問題:(面試福利)
a铐炫、侵入性
b垒手、易用性
c、拓展性 - 蘋果原生:NSJSONSerialization(性能最好的)
三倒信、JSON的解析——NSJSONSerialization
1科贬、JSON -> OC 反序列化
/*
* 第一個參數(shù):json的二進制數(shù)據(jù)
* 第二個參數(shù):
* NSJSONReadingMutableContainers = (1UL << 0),得到OC對象是可變的
* NSJSONReadingMutableLeaves = (1UL << 1), 字典和數(shù)組中的字符串都是可變的,iOS7以后出現(xiàn)很多問題鳖悠,一般不會用到
* NSJSONReadingAllowFragments = (1UL << 2) 既不是字典也不是數(shù)組榜掌,則必須使用該枚舉值 如果返回數(shù)據(jù)為@“\"hahahahaha\"”
* 第三個參數(shù):錯誤信息
*/
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
2、OC -> JSON 序列化
/* 注意:并不是所有的OC對象都可以轉(zhuǎn)化為json 例如字符串
* 頂層必須是NSArray或者NSDictionnary
* 所有的元素必須是 NSString, NSNumber, NSArray, NSDictionary, or NSNull
* 字典中所有的key必須是NSStrings類型的
* NSNumbers 不能是無窮大
*/
// 1乘综、提供轉(zhuǎn)化的OC字典
NSDictionary *dic = @{
@"status":@200,
@"content":@"hello",
@"error":@"enen"
};
// 2憎账、判斷OC對象是否可以轉(zhuǎn)換為json對象
BOOL isVaild = [NSJSONSerialization isValidJSONObject:dic];
if (isVaild) {
/*
* 第一個參數(shù):需要序列化的數(shù)據(jù)
* 第二個參數(shù):如果添加就輸出排版美觀效果 如果不添加按照默認輸出
* NSJSONWritingPrettyPrinted = (1UL << 0)
*/
NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}else{
NSLog(@"該對象無法轉(zhuǎn)換");
}
3、Plist文件轉(zhuǎn)換為JSON文件
NSArray *arrayM = [NSArray arrayWithContentsOfFile:@"plist文件目錄"];
NSLog(@"%@",arrayM);
// 這里要先進行序列化
NSData *data = [NSJSONSerialization dataWithJSONObject:arrayM options:NSJSONWritingPrettyPrinted error:nil];
// 說明:不能直接這樣保存卡辰,會導(dǎo)致輸出不是合法的json數(shù)據(jù)胞皱,相當于一個xml文件
// [arrayM writeToFile:@"/Users/Urag/Desktop/apps.json" atomically:YES];
[data writeToFile:@"JSON文件目錄" atomically:YES];
四、JSON的解析——MJExtension
這里只是說一下關(guān)于使用MJExtension遇到關(guān)鍵字沖突時的解決方式九妈。
// 在模型實現(xiàn)中進行關(guān)鍵字的轉(zhuǎn)換 但是侵入性太強 可以到控制器中進行設(shè)置
+ (NSDictionary *)mj_replacedKeyFromPropertyName{
return @{
@"ID":@"id",
};
}
// 控制器中進行設(shè)置
[model mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
return @{
@"ID":@"id",
};
}];
五反砌、XML簡介
因為XML現(xiàn)在用的很少,所以上面在iOS中序列化和反序列化說法有點以偏概全了萌朱,在這里作補充宴树。。嚷兔。
一個常見的XML文檔一般由以下幾部分組成
文檔聲明
元素(Element)
屬性(Attribute)
1森渐、文檔聲明
- <?xml version="1.0" encoding="UTF-8"?>
- 在XML文檔的最前面,必須編寫一個文檔聲明冒晰,用來聲明XML文檔的類型
- 最簡單的聲明
- <?xml version="1.0"?>
- 用encoding屬性說明文檔的字符編碼
- <?xml version="1.0" encoding="UTF-8"?>
2同衣、元素(Element)
- <error>用戶名不存在</error>
- 一個元素包括了開始標簽和結(jié)束標簽
- 擁有內(nèi)容的元素:<video>Fate</video>
- 沒有內(nèi)容的元素:<video/>(簡寫之后)
- 可以嵌套 但是不能交差嵌套 只能由一個根元素
元素的注意點:
- xml中的所有的空格和換行,都會當做具體內(nèi)容處理
3壶运、屬性
- 一個元素可以有多個屬性
- <video name="Fate 第一部" length = "30"/>
- video元素擁有name和length兩個屬性
- 屬性必須用“” 或者‘’擴住
- 實際上耐齐,屬性表示的信息也可以使用子元素來表示,如
<video>
<name>Fate 第一部</name>
<length> 30 </length>
</video>
六、XML的解析方案
1埠况、解析方式:
- DOM 一次性將整個XML文檔加載進入內(nèi)存 比較適合解析小文件
- SAX 從根元素開始耸携。按照順序一個元素一個元素往下解析,比較是和解析大文件
2辕翰、iOS解析
蘋果原生
- NSXMLParser SAX解析方式夺衍,使用簡單
第三方框架
- libxml2 : 純C語言,默認包含子安iOS SDK中喜命,同時支持DOM和SAX的方式解析
- GDataxml:DOM的方式解析沟沙,基于libxml2
XML解析方式的建議 - 小文件: NSXMLParser libxml2
- 大文件:NSXMLParser libxml2 GDataxml
七、XML解析嘗試
1壁榕、SAX 解析方式
// 1矛紫、創(chuàng)建XML解析器:SAX
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 2、設(shè)置代理 <NSXMLParserDelegate>
parser.delegate = self;
// 3牌里、開始解析阻塞的方法
[parser parse];
// 代理方法的介紹
// 1颊咬、開始解析時調(diào)用
- (void)parserDidStartDocument:(NSXMLParser *)parser{
}
// 2、開始解析某個元素
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
NSLog(@"開始解析某個元素 %@ ===== %@",elementName,attributeDict);
// 使用XML的時候記得過濾根元素
// 字典轉(zhuǎn)模型在這里實現(xiàn)就可以了
}
// 3牡辽、某個元素解析完畢
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
NSLog(@"某個元素解析完畢%@",elementName);
}
// 4喳篇、結(jié)束解析時調(diào)用
- (void)parserDidEndDocument:(NSXMLParser *)parser{
}
2、DOM 解析方式
/*
* 使用GDataXML來進行XML的解析 先要進行以下配置 而且記得在編譯時要將其改為MRC環(huán)境 -fno-objc-arc
* libxml includes require that the target Header Search Paths contain
* /usr/include/libxml2
* and Other Linker Flags contain
* -lxml2
*/
// 1催享、加載XML文檔
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil];
// 2杭隙、拿到根元素,得到所有子孫元素
NSArray * elements = [doc.rootElement elementsForName:@"root"];
// 3哟绊、遍歷操作
for (GDataXMLElement *ele in elements) {
// 元素內(nèi)部所有的屬性-->模型
GHModel * model = [[GHModel alloc] init];
model.name = [ele attributeForName:@"name"].stringValue;
// 將模型存入數(shù)組因妙,作為數(shù)據(jù)源使用
[self.data addObject:model];
}
八、控制臺打印JSON數(shù)據(jù)的中文輸出
/*
* 控制中文輸出核心是重寫系統(tǒng)的description方法
*/
@implementation NSDictionary (log)
// 重寫系統(tǒng)的方法控制輸出
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level{
NSMutableString *str = [NSMutableString string];
//{}
[str appendString:@"{\n"];
// 拼接key-value
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[str appendFormat:@"\t%@",key];
[str appendString:@" : "];
[str appendFormat:@"%@,\n",obj];
}];
[str appendString:@"}"];
// 刪除逗號 從后往前搜索票髓,第一個符號的位置
NSRange range = [str rangeOfString:@"," options:NSBackwardsSearch];
if (range.location != NSNotFound) {
[str deleteCharactersInRange:range];
}
return str;
}
@end
@implementation NSArray(log)
// 重寫系統(tǒng)的方法控制輸出
- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level{
NSMutableString *str = [NSMutableString string];
//{}
[str appendString:@"[\n"];
// 拼接obj
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[str appendFormat:@"\t%@,\n",obj];
}];
[str appendString:@"]"];
// 刪除逗號 從后往前搜索攀涵,第一個符號的位置 如果找到了就刪除
NSRange range = [str rangeOfString:@"," options:NSBackwardsSearch];
if (range.location != NSNotFound) {
[str deleteCharactersInRange:range];
}
return str;
}