CNLiveURLRequestSerialization.m 4.6 KB
//
//  CNLiveUserURLRequestSerialization.m
//  CNLiveHttpRequestDemo
//
//  Created by Android on 16/7/26.
//  Copyright © 2016年 Android. All rights reserved.
//

#import "CNLiveURLRequestSerialization.h"

@interface CNLiveUserURLRequestSerialization ()

@property (readwrite, nonatomic, strong) id value;

@property (readwrite, nonatomic, strong) id field;

@end

@implementation CNLiveUserURLRequestSerialization

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

#pragma mark -

FOUNDATION_EXPORT NSArray * CNUserQueryStringPairsFromDictionary(NSDictionary *dictionary);
FOUNDATION_EXPORT NSArray * CNUserQueryStringPairsFromKeyAndValue(NSString *key, id value);

+ (NSString *)CNUserQueryStringFromParameters:(NSDictionary *)parameters
{
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (CNLiveUserURLRequestSerialization *pair in CNUserQueryStringPairsFromDictionary(parameters)) {
        [mutablePairs addObject:[pair URLEncodedStringValue]];
    }
    return [mutablePairs componentsJoinedByString:@"&"];
}

NSArray * CNUserQueryStringPairsFromDictionary(NSDictionary *dictionary)
{
    return CNUserQueryStringPairsFromKeyAndValue(nil, dictionary);
}

/**
 *  处理上传参数
 */
NSArray * CNUserQueryStringPairsFromKeyAndValue(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;
        for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]]) {
            id nestedValue = dictionary[nestedKey];
            if (nestedKey) {
                [mutableQueryStringComponents addObjectsFromArray:CNUserQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
            }
        }
    }
    
    else if ([value isKindOfClass:[NSArray class]]){   //数组
        NSArray *array = value;
        for (id nestedValue in array) {
            [mutableQueryStringComponents addObjectsFromArray:CNUserQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
        }
    }else if ([value isKindOfClass:[NSSet class]]){   //集合
        NSSet *set = value;
        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            [mutableQueryStringComponents addObjectsFromArray:CNUserQueryStringPairsFromKeyAndValue(key, obj)];
        }
    }else{  //其他类型
        [mutableQueryStringComponents addObject:[[CNLiveUserURLRequestSerialization alloc] initWithField:key value:value]];
    }
    
    return mutableQueryStringComponents;
}

static NSString * CNPercentEscapedStringFromString(NSString *string) {
    static NSString * const kCNCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
    static NSString * const kCNCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
    
    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [allowedCharacterSet removeCharactersInString:[kCNCharactersGeneralDelimitersToEncode stringByAppendingString:kCNCharactersSubDelimitersToEncode]];
    
    
    static NSUInteger const batchSize = 50;
    
    NSUInteger index = 0;
    NSMutableString *escaped = @"".mutableCopy;
    
    while (index < string.length) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu"
        NSUInteger length = MIN(string.length - index, batchSize);
#pragma GCC diagnostic pop
        NSRange range = NSMakeRange(index, length);
        
        range = [string rangeOfComposedCharacterSequencesForRange:range];
        
        NSString *substring = [string substringWithRange:range];
        NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
        [escaped appendString:encoded];
        
        index += range.length;
    }
    
    return escaped;
}

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


@end