ios字典转json字符串带来格式符的坑

背景交代:
因为请求需要签名,签名要拼上请求参数的json字符串。发现一个问题,ios把参数转成json后会有一些类似空格和\n这样的格式符。导致算出来的签名是带上这些格式符的。服务端从请求体拿到的是个字典对象key=value,是没有这些格式符的。所有会签名校验失败。

因为这是ios字典转json产生的格式符,只能ios自己处理。
以下为过滤格式符的代码,暂时解决了有格式符产生算出签名不一致的问题。

    NSString *messageJSON = @"";
    if (![NSJSONSerialization isValidJSONObject:encodePram]) {
        NSLog(@"不是有效的json类型");
        return @"";
    }else
    {
        messageJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:encodePram options:NSJSONWritingPrettyPrinted error:NULL] encoding:NSUTF8StringEncoding];
        
    }
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r\n" withString:@"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString : @"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\t" withString : @"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@" " withString : @"" ];

但是又引入一个问题,就是如果key或者value有空格和\n这类的格式符,那么真正有意义的内容就会被无意修改到,也会导致签名不对。

后来我想到的解决办法是,在转json前先把key和value进行urlencode,这时候出来的字符串就是带了json格式多余的那些空格和\n的,而内容key和value已经被urlencode,这时候过滤json格式符不会把真正的内容过滤掉。

过滤完之后,再对整个字符串来个urlDecode,问题解决。

+ (NSString *)yxNetWorkJsonString:(id)pram{
    if (!([pram isKindOfClass:[NSDictionary class]]||[pram isKindOfClass:[NSArray class]])) {
        return @"{}";
    }
    
    if (!pram) {
        return @"{}";
    }
    
    //pram对key和value进行urlencode
    id encodePram = [self urlEncodeKeyAndValue:pram];
    
    NSString *messageJSON = @"";
    if (![NSJSONSerialization isValidJSONObject:encodePram]) {
        NSLog(@"不是有效的json类型");
        return @"";
    }else
    {
        messageJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:encodePram options:NSJSONWritingPrettyPrinted error:NULL] encoding:NSUTF8StringEncoding];
        
    }
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r\n" withString:@"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n" withString : @"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\t" withString : @"" ];
    messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@" " withString : @"" ];
    
    //对整个字符串url decode
    messageJSON = [messageJSON jk_urlDecode];
    return messageJSON;
}

递归encode

+ (id)urlEncodeKeyAndValue:(id)target
{
    if (!([target isKindOfClass:[NSDictionary class]]||[target isKindOfClass:[NSArray class]])) {
        return nil;
    }
    if ([target isKindOfClass:[NSDictionary class]]) {
        NSMutableDictionary *result = [NSMutableDictionary new];
        [target enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            id NewKey = key;
            id NewValue = obj;
            if ([key isKindOfClass:[NSString class]]) {
                NewKey = [key jk_urlEncode];
            }
            if ([obj isKindOfClass:[NSString class]]) {
                NewValue = [obj jk_urlEncode];
            }else if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]])
            {
                NewValue = [self urlEncodeKeyAndValue:obj];
            }
            [result setObject:NewValue forKey:NewKey];
        }];
        return result;
    }else
    {
        //array
        NSMutableArray * result = [NSMutableArray new];
        
        [target enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            id NewValue = obj;

            if ([obj isKindOfClass:[NSString class]]) {
                NewValue = [obj jk_urlEncode];
            }else if ([obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]])
            {
                NewValue = [self urlEncodeKeyAndValue:obj];
            }
            [result addObject:NewValue];
        }];
        
        
        return result;
    }
}

你可能感兴趣的:(ios字典转json字符串带来格式符的坑)