适当的JSON编码在iOS的HTTP POST请求

发布了一个以前关于JSONparsing无法正常工作的查询。 用包嗅探器和另一个正常工作的客户端进行了更多的研究,发现它是一个语法的东西,我仍然无法解决。

底部的代码使得HTTP请求中包含JSON:{“key”:“value”}

而我的服务器实际上是在下面的语法中寻找一个JSON:key =%22value%22

我试图编写一些手动执行此操作的代码,但认为iOS中必须有一些开箱即用的function,而且我不想在将来出现任何故障。

我搞砸了一会儿,试图find正确的代码的工作,但不能(你可以看到我试过一些代码注释掉)。 谁能帮我?

+ (NSString*)makePostCall:(NSString*)urlSuffix keys:(NSArray*)keys objects:(NSArray*)objects{ NSDictionary *params = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; // NSString *dataString = [self getDataStringFromDictionary:params]; // NSData *jsonData = [dataString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error]; // id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error]; // NSLog(@"%@", jsonObject); if (!jsonData) { // should not happen NSError *error; NSLog(@"Got an error parsing the parameters: %@", error); return nil; } else { // NSString *jsonRequest = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; // NSLog(@"%@", jsonRequest); NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", urlPrefix, urlSuffix]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]; // NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding]; [request setHTTPMethod:@"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; // [request setValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; [request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody: jsonData]; NSURLResponse * response = nil; NSError * error = nil; NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; // TODO: handle error somehow NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; return returnString; } } 

你说:

发生的事情是,服务器期望的每个参数的内容实际上是JSON,但是每个参数都是分开发送的

如果你说你正在发布一个标准的application/x-www-form-urlencoded ,但是想要JSON编码值,这有点不同寻常(我要么只使用JSON或者x-www-form-urlencoded ,但不能把它们结合起来),但这并不难。 如您的示例所示,关键问题是您必须以百分比方式转义生成的JSON。 例如:

 NSURL *url = [NSURL URLWithString:kURLString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"]; // information to be encoded for first parameter NSDictionary *value1 = @{@"name" : @"Dwayne Johnson", @"age" : @41, @"sex" : @"male"}; NSError *error; NSData *json1 = [NSJSONSerialization dataWithJSONObject:value1 options:0 error:&error]; NSAssert(json1, @"Unable to create JSON for value1: %@", error); // information to be encoded for second parameter NSDictionary *value2 = @{@"name" : @"Lauren Hashian", @"age" : @29, @"sex" : @"female"}; NSData *json2 = [NSJSONSerialization dataWithJSONObject:value2 options:0 error:&error]; NSAssert(json2, @"Unable to create JSON for value1: %@", error); // combine these parameters into single dictionary NSDictionary *parameters = @{@"person" : json1, @"partner" : json2}; NSData *requestData = [self encodePostParameters:parameters]; [request setHTTPBody:requestData]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (!data) { NSLog(@"sendAsynchronousRequest failed: %@", connectionError); return; } NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); // you can now use that `responseString` variable (but do this here, // inside this completion block!) }]; 

这将导致请求HTTPBody

 person=%7B%22age%22%3A41%2C%22name%22%3A%22Dwayne+Johnson%22%2C%22sex%22%3A%22male%22%7D&partner=%7B%22age%22%3A29%2C%22name%22%3A%22Lauren+Hashian%22%2C%22sex%22%3A%22female%22%7D 

这里有趣的逻辑是转义百分比,我在方法中调用percentEscapeString ,我从encodePostParameters调用,定义如下:

 /** Percent escape the post parameters for x-www-form-urlencoded request * * @param parameters A NSDictionary of the parameters to be encoded * * @return The NSData to be used in body of POST request (or URL or GET request) */ - (NSData *)encodePostParameters:(NSDictionary *)parameters { NSMutableArray *results = [NSMutableArray array]; for (NSString *key in parameters) { NSString *string; id value = parameters[key]; if ([value isKindOfClass:[NSData class]]) { string = [[NSString alloc] initWithData:value encoding:NSUTF8StringEncoding]; } else if ([value isKindOfClass:[NSString class]]) { string = value; } else { // if you want to handle other data types, add that here string = [value description]; } [results addObject:[NSString stringWithFormat:@"%@=%@", key, [self percentEscapeString:string]]]; } NSString *postString = [results componentsJoinedByString:@"&"]; return [postString dataUsingEncoding:NSUTF8StringEncoding]; } /** Percent escape string * * Note, this does not use `stringByAddingPercentEscapesUsingEncoding`, because * that that will not percent escape some critical reserved characters (notably * `&` and `+`). This uses `CFURLCreateStringByAddingPercentEscapes`, instead. */ - (NSString *)percentEscapeString:(NSString *)string { NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, (CFStringRef)@" ", (CFStringRef)@":/?@!$&'()*+,;=", kCFStringEncodingUTF8)); return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"]; }