You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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ş

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:22:44