如何在NSDictionary中POST一个NSDictionary的NSArray而不会出现问题


How can I POST an NSArray of NSDictionaries inside an NSDictionary without problems?

我知道怎么做,这很简单。

问题是它不起作用。

下面是我用来POST数据的函数:

- (void)updateWebsitesUsingParameters:(NSDictionary *)parameters;
{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [manager POST:@"http://notreal/updateWebsites.php"
       parameters:parameters
          success:^(AFHTTPRequestOperation *operation, id responseObject) {
              NSLog(@"JSON: %@", responseObject);
              //...
          }
          failure:^(AFHTTPRequestOperation *operation, NSError *error) {
              //...
          }];
}

参数如下:

NSDictionary *parameters = @{@"type" : @"0",
                             @"credentials" : @{@"email" : @"notreal@gmail.com", @"password" : @"notreal"},
                             @"device" : @{@"ID" : @"8588107756600540", @"numberOfSessions" : @"0", @"name" : @"Nick's iMac"},
                             @"websites" : @[@{@"title" : @"Google", @"URL" : @"http://www.google.com"}, @{@"title" : @"Yahoo", @"URL" : @"http://www.yahoo.com"}]};

下面是MySQL字段中保存的内容:

[{URL = "http://www.google.com";},{title = Google;},{URL = "http://www.yahoo.com";},{title = Yahoo;}]

这太疯狂了!

  1. 我已经成功地保存了JSON的字典数组与多个属性在一个MySQL字段内的字典-或简而言之,我想做这里-使用PHP脚本用于不同的目的,它的工作,没有问题。
  2. 我使用相同的PHP代码将其保存到MySQL字段,所以这不是PHP的错。
  3. 所有其他保存/检索功能,我已经使用AFNetworking工作完美。

如此:

@[@{@"title" : @"Google"}, @{@"title" : @"Yahoo"}]

这并不:

@[@{@"title" : @"Google", @"URL" : @"http://www.google.com"}, @{@"title" : @"Yahoo", @"URL" : @"http://www.yahoo.com"}]

回复如下:

{
    websites =     (
                {
            URL = "http://www.google.com";
        },
                {
            title = Google;
        },
                {
            URL = "http://www.yahoo.com";
        },
                {
            title = Yahoo;
        }
    );
}

疯狂!

由于某些原因,如果我添加一个额外的属性,它就会崩溃。

这一定是一个AFNetworking bug,因为它没有任何意义。

编辑:

我可以:

  1. 创建两个MySQL字段:websiteTitles, websiteURLs.

  2. 将其保存为一个字符串:"Google;http://www.google.com",然后将其分开,但这违背了使用JSON的目的

  3. 将参数分成两半发送:websteTitles, websiteURLs

都很丑,有什么主意吗?

编辑2:

我运行了一些测试:

不管数组有1个还是2个元素,它都是这样的

我尝试了rob180的建议,正如预期的那样,这是AFNetwokring的错误:

{
    websites =     (
                {
            URL = "http://www.google.com";
        },
                {
            title = Google;
        },
                {
            URL = "http://www.yahoo.com";
        },
                {
            title = Yahoo;
        }
    );
}

这是应用程序发送的实际服务器响应,中间没有mysql

编辑3:

REQUEST: <NSMutableURLRequest: 0x7f9352d467e0> { URL: http://notreal/updateWebsites.php }

HTTPBody看起来像这样:

<63726564 656e7469 616c735b ... 653d30>

我怎么解码这个?

此外,我正在使用AFHTTPRequestSerializer。也许,如果我把它改成AFJSONRequestSerializer它会解决这个问题,但我真的不想,因为我已经写了很多这样的方法。

"查询字符串参数化不是对嵌套数据结构进行编码的可靠方法。这就是为什么所有现代web框架都有内置的便利,可以自动将传入的JSON解码为参数。 - matt Thompson

所以,JSON它是…

参数:

NSDictionary *parameters = @{@"websites" : @[@{@"Title" : @"Google", @"URL" : @"http://www.google.com"}, @{@"Title" : @"Yahoo", @"URL" : @"http://www.yahoo.com"}]};

发送:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    [manager POST:@"http://server/path/file.php"
       parameters:parameters
          success:^(NSURLSessionDataTask *task, id responseObject) {
              NSLog(@"JSON: %@", responseObject);
          }
          failure:^(NSURLSessionDataTask *task, NSError *error) {
              NSLog(@"Error: %@", error.description);
          }];
检索:

<?php
header('Content-type: application/json');
$request = json_decode(file_get_contents('php://input'), TRUE);
$response = ["URLOfTheSecondWebsite" => $request['websites'][1]['URL']];
echo json_encode($response);
?>

反应:

{
    URL = "http://yahoo.com";
}

全部完成!

精金

更新函数AFQueryStringPairsFromKeyAndValue

改变
     for (id nestedValue in array) {
         [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
     }

     int i = 0;
     for (id nestedValue in array) {
         [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[%d]", key, i++], nestedValue)];
     }

AFHTTPSessionManager有相同的问题。不幸的是,你必须切换到AFJSONRequestSerializer来发送字典数组:

manager.requestSerializer = [AFJSONRequestSerializer serializer];

AFJSONRequestSerializer设置application/json content-type和服务器,期望json将成功接受请求参数,而AFHTTPRequestSerializer将始终具有text/html content-type在header中,即使您显式设置。