PHP REST服务从AFNetworking 2.0接收POST时出现JSON格式问题


JSON format issue in PHP REST service receiving POST from AFNetworking 2.0

我有一种情况,我使用AFNetworking 2.0代码从iOS代码中发布JSON字符串。我的客户端代码如下:

NSURL *url = [NSURL URLWithString:BaseURLString];
NSString *jsonString = [[NSString alloc] initWithData:jsonPayloadForProject encoding:NSUTF8StringEncoding];
NSDictionary *parameters = @{@"project": jsonString};
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]       initWithBaseURL:url];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
[manager POST:@"service.php" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"%@", [responseObject description]);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"POST JSON for Project Error"
                                                        message:[error localizedDescription]
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
    [alertView show];
}];

JSON如下所示:

{
  "Maps" : [
    {
      "Markers" : [
        {
          "marker_tag" : -790386438,
          "location_y" : 182,
          "location_x" : 344
        },
        {
          "marker_tag" : 451496476,
          "location_y" : 267,
          "location_x" : 150.5
        }
      ],
      "image_string" : "EC817509-DE49-4914-840E-5E407571F6AE.jpeg",
      "order_num" : 0,
      "name" : "Blah1",
      "id" : "EC817509-DE49-4914-840E-5E407571F6AE"
    },
    {
      "Markers" : [
        {
          "marker_tag" : -79601351,
          "location_y" : 377,
          "location_x" : 486.5,
          "image_id" : "Blah2",
          "map_id" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A"
        }
      ],
      "image_string" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A.jpeg",
      "order_num" : 0,
      "name" : "1st floor",
      "id" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A"
    }
  ],
  "longitude" : "-222.222222",
  "latitude" : "33.33333"
}

当我使用在php代码中读取服务器上的JSON字符串时

$json_str = file_get_contents('php://input');

当我这样做时,我得到以下字符串:

{ "project" = '{ 'n '"Maps'" : [ 'n { 'n '"Markers'" : [ 'n { 'n '"marker_tag'n : = -790386438, 'n ....

我的问题是,当我做以下事情时,我一无所获。

$array_str = json_decode($json_str, true);

将其放入数组以解析数据的最佳方法是什么?如何取回我从客户端发送的原始JSON字符串?

的几个问题

  1. 您的AFHTTPSessionManager使用默认的AFJSONResponseSerializer,但仅覆盖acceptableContentTypes。只有当您的服务器代码真的返回JSON,并且没有在Content-Type头中指定JSON时,您才会这样做。

    • 如果服务器真的没有返回JSON,而不是更改acceptableContentTypes,那么您应该简单地使用AFHTTPSessionManager

      manager.responseSerializer = [AFHTTPResponseSerializer serializer];
      
    • 或者让服务器返回JSON,并确保它指定了正确的Content-Type标头:

      <?php
      $json_str = file_get_contents('php://input');
      $json = json_decode($json_str, true);
      header('Content-Type: application/json');
      $result = array("received" => $json);
      echo json_encode($result);
      ?>
      

      完成此操作后,我现在可以简单地从客户端代码中完全删除acceptableContentTypes行,并继续使用默认的AFJSONResponseSerializer

  2. 所演示的构建parameters的机制是不正确的。您正在创建一个JSON字典,其中只有一个项,它本身就是JSON的字符串表示。

    我建议您将实际的字典放入字典中,而不是将字符串表示放入字典中。所以,如果您真的有一个JSON的NSData,请将其转换回嵌套的NSDictionary/NSArray结构:

    NSError *error;
    id jsonPayload = [NSJSONSerialization JSONObjectWithData:jsonPayloadData options:0 error:&error];
    NSAssert(jsonPayload, @"json parsing error: %@", error);
    NSDictionary *parameters = @{@"project": jsonPayload};
    

    现在,最有可能的是,使用dataWithJSONObject创建一个NSData会有点傻,只是为了转身将其提取出来,但您只需要在parameters中使用原始的NSDictionary,但希望这说明了这一点。

因此,综合所有这些,假设您更改服务器代码以返回正确格式化的JSON响应,如上所述,客户端代码现在变成:

NSError *error;
id jsonPayload = [NSJSONSerialization JSONObjectWithData:jsonPayloadData options:0 error:&error];
NSAssert(jsonPayload, @"json parsing error: %@", error);
NSDictionary *parameters = @{@"project": jsonPayload};
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
// manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
[manager POST:@"service.php" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"%@", [responseObject description]);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"error=%@", error);
}];

如果你这样做,你将成功地将JSON请求发送到服务器,它将被解析,插入到一个新的关联数组中,转换回JSON并返回到客户端应用程序,客户端应用程序将使用默认的AFJSONResponseSerializer来解析并记录它