AFNetworking3.1.0源码分析(六)详解AFHTTPRequestSerializer 之序列化NSMutableURLRequest
来源:互联网 发布:人工智能和大数据 编辑:程序博客网 时间:2024/06/05 23:55
本文主要分析AFNetworking序列化NSMutableURLRequest
1:AFNetworking支持三种media-type对应的http请求头字段Content-Type为:
①application/x-www-form-urlencoded
②application/json
③application/x-plist
在http请求中,请求方式为(GET,HEAD,DELEATE)都使用第①中第一种,因为这三种方式的请求参数是放在URI中,其它的(POST,PUT等)放在请求体中,对于AFNetworking默认也是支持第一种方式。
AFNetworking支持的三种方式支持的序列化请求对象和解析请求参数类有一下三个:
AFHTTPRequestSerializer
AFJSONRequestSerializer :AFHTTPRequestSerializer
AFPropertyListRequestSerializer :AFHTTPRequestSerializer
下面先说下对于application/x-www-form-urlencoded 通用标准的解析请求参数的方式
解析原理:递归解析参数,直到出现参数中最终的结构为key :value(没有嵌套类型)时生成AFQueryStringPair对象,最终生成了所有key:value方式的AFQueryStringPair对象的数组
,然后对数组中的每个对象进行百分号编码,最终使用&拼接,生成最终的query字符串。示例:
①:{"key":[{"key":"value1"},{"key":"value2"},"key1"],"key2":"value3"} --->②:key[][key]=value1&key[][key]=value2&key[]=key1&key2=value3 --->③:key%5B%5D%5Bkey%5D=value1&key%5B%5D%5Bkey%5D=value2&key%5B%5D=key1&key2=value3//①-->②FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary);FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value);//②-->③NSString * AFQueryStringFromParameters(NSDictionary *parameters)
以上三个类都遵循序列化协议:
@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>/** 对原始请求对象进行copy(即序列化原始request,因为从NSURLRequest定义 @interface NSURLRequest : NSObject <NSSecureCoding, NSCopying, NSMutableCopying> 可以知道内部已经实现了序列化协议,可以直接使用mutableCopy来序列化) @param request 原始请求对象 @param parameters 需要编码的请求参数 @param error 编码请求参数过程中出现的错误信息 @return 返回值为经过序列化之后的请求对象 */- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(nullable id)parameters error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;@end
AFHTTPRequestSerializer实现序列化请求对象的方式:
①:序列化原始请求对象:
//验证原始request是否为空,如果为空就输出错误日志信息,并结束程序 NSParameterAssert(request); //深拷贝原始request对象,并设置新request对象的请求头参数 NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }];
②:解析并生成query string,此处可以实现自定义的解析方式,AFNetworking抛出的有接口 queryStringSerialization block对象,默认是按照上面的application/x-www-form-urlencoded方式:
NSString *query = nil; if (parameters) { if (self.queryStringSerialization) {//如果自己实现了对参数的解析,就调用自定义的参数解析 NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); if (serializationError) { if (error) { *error = serializationError; } return nil; } } else { //默认的解析方式有AFNetworking自己实现对参数的解析并生成query字符串 switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: query = AFQueryStringFromParameters(parameters); break; } } }
③:设置Content-Type 和处理URI,如果是老三样(GET,HEAD,DELETE)按照RFC的规范这几种请求方式的请求参数是放在url query部分,显式的呈现在URI中,并且是默认使用application/x-www-form-urlencoded,如果是其它的(POST,PUT)则设置Content-Type为application/x-www-form-urlencoded同时设置请求体参数。因此需要做如下的判断:
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { if (query && query.length > 0) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; } } else { // #2864: an empty string is a valid x-www-form-urlencoded payload if (!query) { query = @""; } //其它方式的请求如(POST PUT )设置httpBody,默认设置Content-Type为form表单提交形式 if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; }
AFJSONRequestSerializer实现序列化请求对象的方式:
①:序列化原始请求对象:
如果是(GET,HEAD,DELETE)方式直接调用父类的序列化解析:
NSParameterAssert(request); if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { return [super requestBySerializingRequest:request withParameters:parameters error:error]; }
如果是(POST,PUT)方式先序列化原始请求对象并设置请求参数:
NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }];
②:设置Content-Type为application/json
if (parameters) { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; }
③:解析请求参数为jsondata并设置请求体参数:
if (![NSJSONSerialization isValidJSONObject:parameters]) { if (error) { NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"The `parameters` argument is not valid JSON.", @"AFNetworking", nil)}; *error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo]; } return nil; } NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]; if (!jsonData) { return nil; } [mutableRequest setHTTPBody:jsonData]; }
AFPropertyListRequestSerializer实现序列化请求对象的方式:
①:序列化原始请求对象:
如果是(GET,HEAD,DELETE)方式直接调用父类的序列化解析:
NSParameterAssert(request); if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { return [super requestBySerializingRequest:request withParameters:parameters error:error]; }
如果是(POST,PUT)方式先序列化原始请求对象并设置请求参数:
NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }];
②:设置Content-Type为application/x-plist
if (parameters) { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-plist" forHTTPHeaderField:@"Content-Type"]; }
③:解析请求参数为jsondata并设置请求体参数:
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]; if (!plistData) { return nil; } [mutableRequest setHTTPBody:plistData];
- AFNetworking3.1.0源码分析(六)详解AFHTTPRequestSerializer 之序列化NSMutableURLRequest
- AFNetworking3.1.0源码分析(五)详解AFHTTPRequestSerializer 之创建NSMutableURLRequest
- AFNetworking3.1.0源码分析(三)AFHTTPRequestSerializer 之AFQueryStringPair
- AFNetworking3.1.0源码分析(四)详解AFHTTPRequestSerializer 之初始化方法
- AFNetworking3.1.0源码分析(七)详解AFHTTPRequestSerializer 之AFStreamingMultipartFormData上
- AFNetworking3.1.0源码分析(八)AFHTTPRequestSerializer 之AFStreamingMultipartFormData下
- AFNetworking3.1.0源码分析(九)AFHTTPRequestSerializer 之解决调用Amazon S3 服务出现的bug
- AFNetworking3.1.0源码分析(十)之AFSecurityPolicy
- AFNetworking3.1.0源码分析(十一)之AFSecurityPolicy验证服务器信任
- AFNetworking3.1.0源码分析(一)整体框架和功能模块
- AFNetworking3.1.0源码分析(十二)AFURLResponseSerialization
- AFNetworking3.1.0源码分析(十四)AFHTTPSessionManager
- AFNetworking3.1.0源码分析(十三)AFURLSessionManager
- AFNetworking3.0源码解读(一)之 AFNetworkReachabilityManager
- iOS 之 AFNetWorking3.1.0
- kubenetes源码分析之DNS(六)
- Zookeeper源码分析之序列化
- 时间序列分析之六:应用
- 解决IllegalStateException: Can not perform this action after onSaveInstanceState
- 第一篇
- apache报中文“以一种访问权限不允许的方式做了一个访问套接字的尝试”
- 后台管理系统
- Android编码规范
- AFNetworking3.1.0源码分析(六)详解AFHTTPRequestSerializer 之序列化NSMutableURLRequest
- 9 python txt文件读写操作
- LBS应用的数据设计方法
- 子线程执行进度条
- RecycleView的基本配置和使用方法(二)---RecycleView实践应用
- js删除数组元素、清空数组的简单方法
- 遗迹系列 -【学渣告诉你】到底神马是傅里叶级数!
- JS 提交form表单
- informix-dbschema