AFNetwork 3.0 源码解读(四)AFURLResponseSerialization

来源:互联网 发布:js中的offsettop 编辑:程序博客网 时间:2024/04/30 04:36
AFURLResponseSerialization相对于AFURLRequestSerialization,一个是网络请求的序列化,一个是网络响应的序列化。AFURLResponseSerialization是将网络请求回来的数据解析检查数据是否合法,把NSData数据转成相应的对象

在AFURLResponseSerialization类中包含了:
AFURLResponseSerialization协议
AFHTTPResponseSerializer
AFHTTPResponseSerializer的子类们
AFJSONResponseSerializer
AFXMLParserResponseSerializer
AFImageResponseSerializer

主要的检测方法:
/// 解析response为对应的数据类型(JSON、XML、plist、Image)
- (nullableid)responseObjectForResponse:(nullableNSURLResponse *)response
                           data:(nullableNSData *)data
                                   error:(NSError *_Nullable__autoreleasing *)error;

/// 使用此方法来检测当前的response是否有限
- (BOOL)validateResponse:(nullableNSHTTPURLResponse *)response
                    data:(nullableNSData *)data
                   error:(NSError *_Nullable __autoreleasing *)error;

  • – validateResponse:data:error:方法主要是通过验证MIMEType数据类型),StatusCode(状态码:2xx为成功状态)是否满足条件来判断网络返回的数据是否有效,
– responseObjectForResponse:data:error: 方法主要作用是对返回的数据进行解析,AFHTTPResponseSerializer的子类会重写这个方法,根据不同的需要解析成不同的结果,如AFJSONResponseSerializer会将数据解析成为JSON数据,

以AFJSONResponseSerializer的解析为例如下:

Data转JSON的顺序: data -> string -> data -> JSON
- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(
NSData *)data
                          error:(
NSError *__autoreleasing *)error
{
          /// 判断返回的数据是否成功
    if (![selfvalidateResponse:(NSHTTPURLResponse *)responsedata:dataerror:error]) {
       
if (!error ||AFErrorOrUnderlyingErrorHasCodeInDomain(*error,NSURLErrorCannotDecodeContentData,AFURLResponseSerializationErrorDomain)) {
           
returnnil;
        }
    }

    NSStringEncoding stringEncoding =self.stringEncoding;
   
if (response.textEncodingName) {
       
CFStringEncoding encoding =CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
       
if (encoding !=kCFStringEncodingInvalidId) {
            stringEncoding =
CFStringConvertEncodingToNSStringEncoding(encoding);
        }
    }

   
id responseObject =nil;
   
NSError *serializationError =nil;
    @autoreleasepool {
                    /// 根据自己设置的stringEncoding将data先转换成NSString
        NSString *responseString = [[NSStringalloc]initWithData:dataencoding:stringEncoding];
        if (responseString && ![responseString isEqualToString:@" "]) {
                         /// 再将string使用UTF8编码转换成Data
            data = [responseStringdataUsingEncoding:NSUTF8StringEncoding];

           
if (data) {
               if ([data length] > 0) {
                                                  /// 有效的data数据,使用系统自带的NSJSONSerialization转换成JSON
                    responseObject = [NSJSONSerializationJSONObjectWithData:dataoptions:self.readingOptionserror:&serializationError];
                }
else {
                   
returnnil;
                }
            } else {
                /// 错误信息
               NSDictionary *userInfo =@{
                                          
NSLocalizedDescriptionKey:NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string",@"AFNetworking",nil),
                                          
NSLocalizedFailureReasonErrorKey: [NSStringstringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", @"AFNetworking",nil), responseString]
                                          
};

                serializationError = [
NSErrorerrorWithDomain:AFURLResponseSerializationErrorDomaincode:NSURLErrorCannotDecodeContentDatauserInfo:userInfo];
            }
        }
    }

   
if (self.removesKeysWithNullValues && responseObject) {
        responseObject =
AFJSONObjectByRemovingKeysWithNullValues(responseObject,self.readingOptions);
    }

   
if (error) {
        *error =
AFErrorWithUnderlyingError(serializationError, *error);
    }

   
return responseObject;
}
AFJSONResponseSerializer使用系统内置的NSJSONSerialization解析json,NSJSON只支持解析UTF8编码的数据(还有UTF-16LE之类的,都不常用),所以要先把返回的数据转成UTF8格式。这里会尝试用HTTP返回的编码类型和自己设置的stringEncoding去把数据解码转成字符串NSString,再把NSString用UTF8编码转成NSData,再用NSJSONSerialization解析成对象返回。

同时AFJSONResponseSerializer会使用AFJSONObjectByRemovingKeysWithNullValues(responseObject,self.readingOptions)方法;递归会将返回的数据中值为nil或者为NSNull的键移除。。


0 0
原创粉丝点击