适用于iOS中HTTP POST请求的正确JSON编码 [英] Proper JSON encoding for HTTP POST request in iOS

查看:112
本文介绍了适用于iOS中HTTP POST请求的正确JSON编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

先前发布了有关JSON解析无法正常运行的查询.用数据包嗅探器以及另一个运行正常的客户端进行了更多调查,发现这是语法问题,我似乎仍然无法解决.

Posted a query previously about JSON parsing not working properly. Did more looking into it with a packet sniffer and also with another client that works properly and found out it's a syntax thing, that I still can't seem to solve.

底部的代码使HTTP请求中包含JSON,如下所示: {键":值"}

The code in the bottom makes the HTTP request to have the JSON in it as: {"key":"value"}

我的服务器实际上正在使用以下语法查找JSON: 键=%22value%22

And my server is actually looking for a JSON in the following syntax: key=%22value%22

我试图编写一些手动执行此操作的代码,但认为iOS必须有一些开箱即用的功能,而且我也不想在将来出现问题.

I tried to write some code that does this manually, but figured there must be something out of the box for iOS, and I don't want to have faults in the future.

我把它弄乱了一段时间,试图找到适合该工作的代码,但是没能(您可以看到一些我尝试将其注释掉的代码).谁能帮我?

I messed around with it for a while trying to find the right code for the job, but couldn't (you can see some code I tried commented out). Can anyone help me?

+ (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,但是每个参数都是单独发送的

what happens is that the content of each parameter the server expects is actually JSON, but each parameter is sent separately

如果您要发布的是标准application/x-www-form-urlencoded,但想对值进行JSON编码,则这有点不寻常(我只使用JSON或x-www-form-urlencoded,但不将它们组合在一起),但这并不难.如您的示例所示,关键问题是必须百分比转义所得的JSON.例如:

If you're saying that you're issuing a standard application/x-www-form-urlencoded, but want to JSON encode the values, that's a little unusual (I'd either exclusively use JSON or x-www-form-urlencoded, but not combine them), but it's not hard to do. The key issue, as shown in your example, is that you must percent escape the resulting JSON. For example:

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:

That will result in a request HTTPBody of:

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调用,定义如下:

The interesting logic here is the percent escaping, which I do in method called percentEscapeString, which I call from encodePostParameters, which is defined as follows:

/** 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:@"+"];
}

这篇关于适用于iOS中HTTP POST请求的正确JSON编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆