【问题标题】:iOS Send JSON data in POST request using NSJSONSerializationiOS 使用 NSJSONSerialization 在 POST 请求中发送 JSON 数据
【发布时间】:2014-04-06 23:49:35
【问题描述】:

我知道发布了一些类似的问题,尽管我已经阅读了大部分问题,但仍然遇到问题。我正在尝试将 JSON 数据发送到我的服务器,但我认为没有收到 JSON 数据。我只是不确定我错过了什么。下面是我的代码...

向服务器发送数据的方法。

- (void)saveTrackToCloud
{
    NSData *jsonData = [self.track jsonTrackDataForUploadingToCloud];  // Method shown below.
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"%@", jsonString);  // To verify the jsonString.

    NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:http://www.myDomain.com/myscript.php] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
    [postRequest setHTTPMethod:@"POST"];
    [postRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [postRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [postRequest setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
    [postRequest setHTTPBody:jsonData];

    NSURLResponse *response = nil;
    NSError *requestError = nil;
    NSData *returnData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&requestError];

    if (requestError == nil) {
        NSString *returnString = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
        NSLog(@"returnString: %@", returnString);
    } else {
        NSLog(@"NSURLConnection sendSynchronousRequest error: %@", requestError);
    }
}

方法 jsonTrackDataForUploadingToCloud

-(NSData *)jsonTrackDataForUploadingToCloud
{
    // NSDictionary for testing.
    NSDictionary *trackDictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"firstValue", @"firstKey", @"secondValue", @"secondKey", @"thirdValue", @"thirdKey", nil];

    if ([NSJSONSerialization isValidJSONObject:trackDictionary]) {

        NSError *error;
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:trackDictionary options:NSJSONWritingPrettyPrinted error:&error];

        if (error == nil && jsonData != nil) {
            return jsonData;
        } else {
            NSLog(@"Error creating JSON data: %@", error);
            return nil;
        }

    } else {

        NSLog(@"trackDictionary is not a valid JSON object.");
        return nil;
    }
}

这是我的 php。

<?php
    var_dump($_POST);
    exit;
?>

我从NSLog(@"returnString: %@", returnString); 收到的输出是...

returnString: array(0) {
} 

【问题讨论】:

    标签: php ios json post nsjsonserialization


    【解决方案1】:

    在您的 PHP 中,您正在获取 $_POST 变量,该变量用于 application/x-www-form-urlencoded 内容类型(或其他标准 HTTP 请求)。但是,如果您要获取 JSON,则应该检索原始数据:

    <?php
    
        // read the raw post data
    
        $handle = fopen("php://input", "rb");
        $raw_post_data = '';
        while (!feof($handle)) {
            $raw_post_data .= fread($handle, 8192);
        }
        fclose($handle); 
    
        echo $raw_post_data;
    ?>
    

    不过,更有可能的是,您希望获取 JSON $raw_post_data,将 JSON 解码为关联数组($request,在我下面的示例中),然后根据什么构建关联数组 $response在请求中,然后将其编码为 JSON 并返回。我还将设置响应的 content-type 以明确它是 JSON 响应。作为一个随机示例,请参阅:

    <?php
    
        // read the raw post data
    
        $handle = fopen("php://input", "rb");
        $raw_post_data = '';
        while (!feof($handle)) {
            $raw_post_data .= fread($handle, 8192);
        }
        fclose($handle);
    
        // decode the JSON into an associative array
    
        $request = json_decode($raw_post_data, true);
    
        // you can now access the associative array, $request
    
        if ($request['firstKey'] == 'firstValue') {
            $response['success'] = true;
        } else {
            $response['success'] = false;
        }
    
        // I don't know what else you might want to do with `$request`, so I'll just throw
        // the whole request as a value in my response with the key of `request`:
    
        $response['request'] = $request;
    
        $raw_response = json_encode($response);
    
        // specify headers
    
        header("Content-Type: application/json");
        header("Content-Length: " . strlen($raw_response));
    
        // output response
    
        echo $raw_response;
    ?>
    

    这不是一个非常有用的示例(只是检查与firstKey 关联的值是否为'firstValue'),但希望它说明了如何解析请求并创建响应的想法。

    其他几个方面:

    1. 您可能希望包括对响应状态代码的检查(从NSURLConnection 的角度来看,一些随机服务器错误,例如 404 - 找不到页面)不会被解释为错误,因此请检查响应代码.

      您显然可能想使用NSJSONSerialization 来解析响应:

      [NSURLConnection sendAsynchronousRequest:postRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
          if (error) {
              NSLog(@"NSURLConnection sendAsynchronousRequest error = %@", error);
              return;
          }
      
          if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
              NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
              if (statusCode != 200) {
                  NSLog(@"Warning, status code of response was not 200, it was %d", statusCode);
              }
          }
      
          NSError *parseError;
          NSDictionary *returnDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
          if (returnDictionary) {
              NSLog(@"returnDictionary = %@", returnDictionary);
          } else {
              NSLog(@"error parsing JSON response: %@", parseError);
      
              NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
              NSLog(@"returnString = %@", returnString);
          }
      }
      
    2. 我可能建议您应该使用sendAsynchronousRequest,如上所示,而不是同步请求,因为您永远不应该从主队列执行同步请求。

    3. 我的示例 PHP 正在对请求的 Content-type 等进行最少的检查。因此您可能希望进行更强大的错误处理。

    【讨论】:

    • 我会试试这个,让你知道。虽然上面的代码中没有显示,但我的 NSURLConnection 没有在主线程上执行。方法saveTrackToCloud被异步调用。
    • 谢谢!!我刚刚尝试了您的 php 代码,它解决了问题!我昨天花了几个小时来解决这个问题。我想这可能是我的 php 代码,因为我的 php 技能很少。
    • @Rob 使用$raw_post_data$_POST 之间有区别吗?如果您能提供帮助,我似乎有一个问题,正如我的问题中所解释的那样:@987654321 @
    • @Pangu - 是的,有区别。这是此答案中的主要观察结果,即您不能将 $_POST 用于 JSON 请求。您必须捕获原始请求并 json_decode 它。
    【解决方案2】:

    Advanced Rest Client 可以方便地测试您的网络服务。因此,请确保 Web 服务按需要运行,然后在您的客户端应用程序中映射相同的参数。

    【讨论】:

      猜你喜欢
      • 2013-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-11
      相关资源
      最近更新 更多