iOS序列化和反序列化

今天和大家一起來學(xué)習(xí)一下iOS序列化和反序列化,有疏忽的地方,還望各位不吝賜教。


一、序列化和反序列化

序列化: 將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制串的過程。
反序列化:將在序列化過程中所生成的二進(jìn)制串轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對(duì)象的過程。

在iOS中簡(jiǎn)單粗暴的解釋

  • JSON -> OC 反序列化
  • OC -> JSON 序列化

二、JSON簡(jiǎn)介

1、什么是JSON

  • json是一種輕量級(jí)的數(shù)據(jù)格式
  • 服務(wù)器返回給客戶端的數(shù)據(jù),一般都是json或者xml的數(shù)據(jù)
  • 80%都是json

2、JSON和OC的對(duì)應(yīng)關(guān)系

  • 標(biāo)準(zhǔn)的JSON的 key 必須使用雙引號(hào) iOS必須是雙引號(hào)
  • json中的{} 對(duì)應(yīng)OC中的NSDictionary
  • json中的[] 對(duì)應(yīng)OC中的NSArray
  • json中的雙引號(hào) 對(duì)應(yīng)OC中的NSString
  • json中的數(shù)字 對(duì)應(yīng)OC中的NSNumber

3、JSON的解析方案

  • 第三方框架:MJExtension(不需要繼承,代碼沒有侵入性)
    在選用框架時(shí)注意的問題:(面試福利)
    a、侵入性
    b、易用性
    c、拓展性
  • 蘋果原生:NSJSONSerialization(性能最好的)

三、JSON的解析——NSJSONSerialization

1、JSON -> OC 反序列化

 /*
  * 第一個(gè)參數(shù):json的二進(jìn)制數(shù)據(jù)
  * 第二個(gè)參數(shù):
  * NSJSONReadingMutableContainers = (1UL << 0),得到OC對(duì)象是可變的
  * NSJSONReadingMutableLeaves = (1UL << 1), 字典和數(shù)組中的字符串都是可變的,iOS7以后出現(xiàn)很多問題,一般不會(huì)用到
  * NSJSONReadingAllowFragments = (1UL << 2) 既不是字典也不是數(shù)組,則必須使用該枚舉值 如果返回?cái)?shù)據(jù)為@“\"hahahahaha\"”
  * 第三個(gè)參數(shù):錯(cuò)誤信息
  */
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

2、OC -> JSON 序列化

    /* 注意:并不是所有的OC對(duì)象都可以轉(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對(duì)象是否可以轉(zhuǎn)換為json對(duì)象
    BOOL isVaild = [NSJSONSerialization isValidJSONObject:dic];
    if (isVaild) {
        /*
         * 第一個(gè)參數(shù):需要序列化的數(shù)據(jù)
         * 第二個(gè)參數(shù):如果添加就輸出排版美觀效果 如果不添加按照默認(rèn)輸出
         *        NSJSONWritingPrettyPrinted = (1UL << 0)
         */
        NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
        NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }else{
    
        NSLog(@"該對(duì)象無法轉(zhuǎn)換");
    }

3、Plist文件轉(zhuǎn)換為JSON文件

     NSArray *arrayM = [NSArray arrayWithContentsOfFile:@"plist文件目錄"];
    NSLog(@"%@",arrayM);
    
    // 這里要先進(jìn)行序列化
    NSData *data = [NSJSONSerialization dataWithJSONObject:arrayM options:NSJSONWritingPrettyPrinted error:nil];
    // 說明:不能直接這樣保存,會(huì)導(dǎo)致輸出不是合法的json數(shù)據(jù),相當(dāng)于一個(gè)xml文件
    //   [arrayM writeToFile:@"/Users/Urag/Desktop/apps.json" atomically:YES];
    [data writeToFile:@"JSON文件目錄" atomically:YES];

四、JSON的解析——MJExtension

這里只是說一下關(guān)于使用MJExtension遇到關(guān)鍵字沖突時(shí)的解決方式。

// 在模型實(shí)現(xiàn)中進(jìn)行關(guān)鍵字的轉(zhuǎn)換 但是侵入性太強(qiáng) 可以到控制器中進(jìn)行設(shè)置
+ (NSDictionary *)mj_replacedKeyFromPropertyName{

    return @{
             @"ID":@"id",
             };
}
// 控制器中進(jìn)行設(shè)置
[model  mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
        return @{
                 @"ID":@"id",
                 };
    }];

五、XML簡(jiǎn)介

因?yàn)閄ML現(xiàn)在用的很少,所以上面在iOS中序列化和反序列化說法有點(diǎn)以偏概全了,在這里作補(bǔ)充。。。

一個(gè)常見的XML文檔一般由以下幾部分組成
文檔聲明
元素(Element)
屬性(Attribute)

1、文檔聲明

  • <?xml version="1.0" encoding="UTF-8"?>
  • 在XML文檔的最前面,必須編寫一個(gè)文檔聲明,用來聲明XML文檔的類型
  • 最簡(jiǎn)單的聲明
  • <?xml version="1.0"?>
  • 用encoding屬性說明文檔的字符編碼
  • <?xml version="1.0" encoding="UTF-8"?>

2、元素(Element)

  • <error>用戶名不存在</error>
  • 一個(gè)元素包括了開始標(biāo)簽和結(jié)束標(biāo)簽
  • 擁有內(nèi)容的元素:<video>Fate</video>
  • 沒有內(nèi)容的元素:<video/>(簡(jiǎn)寫之后)
  • 可以嵌套 但是不能交差嵌套 只能由一個(gè)根元素

元素的注意點(diǎn):

  • xml中的所有的空格和換行,都會(huì)當(dāng)做具體內(nèi)容處理

3、屬性

  • 一個(gè)元素可以有多個(gè)屬性
  • <video name="Fate 第一部" length = "30"/>
  • video元素?fù)碛衝ame和length兩個(gè)屬性
  • 屬性必須用“” 或者‘’擴(kuò)住
  • 實(shí)際上,屬性表示的信息也可以使用子元素來表示,如
    <video>
    <name>Fate 第一部</name>
    <length> 30 </length>
    </video>

六、XML的解析方案

1、解析方式:

  • DOM 一次性將整個(gè)XML文檔加載進(jìn)入內(nèi)存 比較適合解析小文件
  • SAX 從根元素開始。按照順序一個(gè)元素一個(gè)元素往下解析,比較是和解析大文件

2、iOS解析

蘋果原生

  • NSXMLParser SAX解析方式,使用簡(jiǎn)單

第三方框架

  • libxml2 : 純C語言,默認(rèn)包含子安iOS SDK中,同時(shí)支持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、開始解析時(shí)調(diào)用
- (void)parserDidStartDocument:(NSXMLParser *)parser{
    
}
// 2、開始解析某個(gè)元素
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{

    NSLog(@"開始解析某個(gè)元素 %@ ===== %@",elementName,attributeDict);
    
    // 使用XML的時(shí)候記得過濾根元素
    // 字典轉(zhuǎn)模型在這里實(shí)現(xiàn)就可以了
    
}
// 3、某個(gè)元素解析完畢
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    NSLog(@"某個(gè)元素解析完畢%@",elementName);
}


// 4、結(jié)束解析時(shí)調(diào)用
- (void)parserDidEndDocument:(NSXMLParser *)parser{

}

2、DOM 解析方式

   /*
    *  使用GDataXML來進(jìn)行XML的解析 先要進(jìn)行以下配置 而且記得在編譯時(shí)要將其改為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];
    } 

八、控制臺(tái)打印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:@"}"];
    
    // 刪除逗號(hào) 從后往前搜索,第一個(gè)符號(hào)的位置
    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:@"]"];
    
    // 刪除逗號(hào) 從后往前搜索,第一個(gè)符號(hào)的位置 如果找到了就刪除
    NSRange range = [str rangeOfString:@"," options:NSBackwardsSearch];
    if (range.location != NSNotFound) {
        
        [str deleteCharactersInRange:range];
        
    }
    
    return str;
}

寫在最后的話:關(guān)于iOS序列化和反序列化相關(guān)知識(shí)今天就分享到這里,關(guān)于iOS序列化和反序列化方面的問題歡迎大家和我交流,共同進(jìn)步,謝謝各位。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容