AFNetworking 参数(query,非body)包含数组

先看看需求,GET请求,ParameterType:query,orderStatus是一个数组


image.png

用afn 一般的GET请求 有数组时候 url 是这样

.../orders?...&orderStatus[]=1&orderStatus[]=2...

可是服务端那边获取不到orderStatus,且Android也没有问题,那就只能iOS端修改咯,问Android同事,他的链接是:

.../orders?...&orderStatus=1&orderStatus=2...

没有中括号的形式

解决:AFHTTPRequestSerializer中的方法

- (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, id, NSError *__autoreleasing *))block

在block中返回需要的格式

复制了 afn 自带的query处理的方法

AFQueryStringFromParameters(parameters)

只改一句话

[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];

全部代码

@interface JMAFQueryStringPair : NSObject
@property (readwrite, nonatomic, strong) id field;
@property (readwrite, nonatomic, strong) id value;

- (instancetype)initWithField:(id)field value:(id)value;

- (NSString *)jm_URLEncodedStringValue;
@end

@implementation JMAFQueryStringPair

- (instancetype)initWithField:(id)field value:(id)value {
    self = [super init];
    if (!self) {
        return nil;
    }
    
    self.field = field;
    self.value = value;
    
    return self;
}

- (NSString *)jm_URLEncodedStringValue {
    if (!self.value || [self.value isEqual:[NSNull null]]) {
        return AFPercentEscapedStringFromString([self.field description]);
    } else {
        return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])];
    }
}

@end

NSString * JM_AFQueryStringFromParameters(NSDictionary *parameters) {
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (JMAFQueryStringPair *pair in JM_AFQueryStringPairsFromDictionary(parameters)) {
        [mutablePairs addObject:[pair jm_URLEncodedStringValue]];
    }
    
    return [mutablePairs componentsJoinedByString:@"&"];
}

NSArray * JM_AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
    return JM_AFQueryStringPairsFromKeyAndValue(nil, dictionary);
}

NSArray * JM_AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
    NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
    
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
    
    if ([value isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictionary = value;
        // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
        for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            id nestedValue = dictionary[nestedKey];
            if (nestedValue) {
                [mutableQueryStringComponents addObjectsFromArray:JM_AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
            }
        }
    } else if ([value isKindOfClass:[NSArray class]]) {
        NSArray *array = value;
        for (id nestedValue in array) {
            // afn 原来代码
            [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
            [mutableQueryStringComponents addObjectsFromArray:JM_AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@", key], nestedValue)];
        }
    } else if ([value isKindOfClass:[NSSet class]]) {
        NSSet *set = value;
        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            [mutableQueryStringComponents addObjectsFromArray:JM_AFQueryStringPairsFromKeyAndValue(key, obj)];
        }
    } else {
        [mutableQueryStringComponents addObject:[[JMAFQueryStringPair alloc] initWithField:key value:value]];
    }
    
    return mutableQueryStringComponents;
}

然后在AFHTTPSessionManager创建时候 添加代码

static AFHTTPSessionManager *httpManager = nil;
+ (AFHTTPSessionManager *)shareHttpManager {
    if (!httpManager) {
        httpManager = [AFHTTPSessionManager manager];
        // ... 省略 ...
        [httpManager.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, id parameters, NSError *__autoreleasing *error) {
            return JM_AFQueryStringFromParameters(parameters);
        }];
        // ... 省略 ...
    }
    return httpManager;
}

搞定

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,172评论 1 32
  • AFN什么是AFN全称是AFNetworking,是对NSURLConnection、NSURLSession的一...
    醉叶惜秋阅读 1,266评论 0 0
  • 1、登录(文本输入、按钮交互、基于网络的交互) 2、刷新界面:(表视图) 1>小部分应用程序数据来源于本地 2>更...
    炙冰阅读 836评论 0 1
  • 我们先看一下AFNetworking.h文件都给了我们什么方法 #import <Foundation/Found...
    潇岩阅读 687评论 0 1
  • 1.线性布局(LinearLayout) 按照垂直或者水平方向布局组件,其中的控件可以通过weight属性来平分剩...
    dawsonenjoy阅读 184评论 0 0