iOS Objective-C:x-www-form-urlencoded格式发送JSON结构数据失败
解决iOS Objective-C中正确发送x-www-form-urlencoded格式数据的问题
问题场景
尝试以x-www-form-urlencoded格式发送以下参数时请求失败:
JobId=564876565946&UstaId=242816809697&Comment=&Ratings=[{ QuestionId = 3533; Rating = 4; },{ QuestionId = 9767; Rating = 5; }]
但用Postman发送JSON格式的相同参数(如下)时请求成功:
{ "JobId": 564876565946, "UstaId": 242816809697, "Ratings": [ { "QuestionId": 3533, "Rating": 4 }, { "QuestionId": 9767, "Rating": 4 } ], "Comment": "test postman" }
当前使用的Objective-C参数构造代码:
NSDictionary *params = @{ @"Ratings":[NSString stringWithFormat:@"[%@]",[self.ratings componentsJoinedByString:@","]], @"Comment":comment, @"UstaId":[self.ustaID stringValue], @"JobId":[self.jobID stringValue] };
向self.ratings(NSMutableArray类型)添加数据的代码:
for(RatingQuestion * question in AppDlg.reviewQustions){ self.answer=[[NSMutableDictionary alloc]init]; [self.answer setObject:[question.ID stringValue]forKey:@"QuestionId"]; [self.answer setObject:@5 forKey:@"Rating"]; [self.ratings addObject:self.answer]; }
错误原因
直接调用componentsJoinedByString:拼接数组中的字典,得到的是Objective-C字典的默认描述字符串(格式为{QuestionId = xxx; Rating = yyy;}),但服务端期望Ratings参数是标准JSON格式的字符串(与Postman中的结构一致),这种格式不匹配导致服务端无法解析参数。
解决方案
需要将self.ratings数组转换为标准JSON字符串,再对所有参数进行URL编码,最终拼接成符合x-www-form-urlencoded格式的请求体:
// 1. 将ratings数组转换为标准JSON字符串 NSError *jsonError = nil; NSData *ratingsJsonData = [NSJSONSerialization dataWithJSONObject:self.ratings options:0 error:&jsonError]; NSString *ratingsJsonString = [[NSString alloc] initWithData:ratingsJsonData encoding:NSUTF8StringEncoding]; if (!jsonError) { // 2. 构造基础参数字典 NSDictionary *baseParams = @{ @"Ratings": ratingsJsonString, @"Comment": comment ?: @"", // 处理评论为空的情况 @"UstaId": [self.ustaID stringValue], @"JobId": [self.jobID stringValue] }; // 3. 将参数字典转换为x-www-form-urlencoded格式字符串 NSMutableArray *formParts = [NSMutableArray array]; NSCharacterSet *allowedChars = [NSCharacterSet URLQueryAllowedCharacterSet]; for (NSString *key in baseParams.allKeys) { NSString *value = baseParams[key]; // 对key和value分别进行URL编码,避免特殊字符破坏格式 NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:allowedChars]; NSString *encodedValue = [value stringByAddingPercentEncodingWithAllowedCharacters:allowedChars]; [formParts addObject:[NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue]]; } NSString *formEncodedString = [formParts componentsJoinedByString:@"&"]; // 4. 构建并发送请求 NSURL *requestURL = [NSURL URLWithString:@"你的请求接口地址"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL]; [request setHTTPMethod:@"POST"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:[formEncodedString dataUsingEncoding:NSUTF8StringEncoding]]; // 执行请求(这里可以用NSURLSession或其他网络框架) NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 处理请求结果 if (!error) { // 解析响应数据 } else { NSLog(@"请求失败: %@", error.localizedDescription); } }]; [task resume]; } else { NSLog(@"Ratings转换JSON失败: %@", jsonError.localizedDescription); }
关键说明
- 使用
NSJSONSerialization将数组转为JSON字符串,确保Ratings参数格式与Postman中的结构一致 - 对所有参数的key和value进行URL编码,避免空格、引号等特殊字符导致的格式错误
- 设置正确的
Content-Type请求头为application/x-www-form-urlencoded,告诉服务端请求体的格式
内容的提问来源于stack exchange,提问作者Ali Efe Baruş
相关产品推荐
相关产品推荐

