如何在没有问题的情况下在NSDictionary中发布NSArray NSArray?

时间:2021-01-13 13:43:43

I do know how to do this, it's fairly simple.

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

The problem is that it doesn't work.

问题是它不起作用。

Here's the function I use to POST the data:

这是我用来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) {

              //...
          }];
}

Here are the parameters:

以下是参数:

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"}]};

Here's what gets saved in the MySQL field:

这是在MySQL字段中保存的内容:

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

THIS IS CRAZY!

这太疯狂了!

  1. I have successfully saved JSON of an array of dictionaries with multiple attributes inside a dictionary inside a MySQL field --or in short what I'm trying to do here-- using a PHP script for a different purpose and it works, no problem.
  2. 我已经成功地保存了一个字典数组的JSON,其中包含MySQL字段内​​的字典中的多个属性 - 或者简而言之,我在这里尝试做什么 - 使用PHP脚本用于不同的目的并且它有效,没问题。

  3. I use the same PHP code to save it to the MySQL field so IT'S NOT PHP'S FAULT.
  4. 我使用相同的PHP代码将其保存到MySQL字段,因此它不是PHP的故障。

  5. All other save / retrieve functions I have made using AFNetworking work perfectly.
  6. 我使用AFNetworking完成的所有其他保存/检索功能。

This works:

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

This doesn't:

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

Here's the response:

这是回复:

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

INSANE!

For some reason, it breaks down if I add an extra attribute.

出于某种原因,如果我添加额外的属性,它会崩溃。

This must be an AFNetworking bug because it makes no sense.

这必须是AFNetworking错误,因为它没有任何意义。

EDIT:

I could:

  1. Make two MySQL fields: websiteTitles, websiteURLs.

    制作两个MySQL字段:websiteTitles,websiteURLs。

  2. Save it as one string: "Google;http://www.google.com" and then separate it but that defeats the purpose of using JSON.

    将其保存为一个字符串:“Google; http://www.google.com”,然后将其分开,但这会破坏使用JSON的目的。

  3. Send the parameters chopped in half: websteTitles, websiteURLs

    发送参数切成两半:websteTitles,websiteURLs

All are hideous, any ideas?

一切都是丑陋的,任何想法?

EDIT 2:

I run a few tests:

我做了几个测试:

It doesn't matter if the array has 1 or 2 items it still behaves like this.

如果数组有1个或2个项目,它仍然表现得像这样无关紧要。

I tried what rob180 suggested and --as expected-- it's AFNetwokring's fault:

我尝试了rob180建议的东西,而且 - 这是预期的 - 这是AFNetwokring的错:

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

This is the actual server response of what has been send from the app, no mysql in the middle.

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

EDIT 3:

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

The HTTPBody looks like this:

HTTPBody看起来像这样:

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

How can I decode this?

我怎么解码这个?

Also, I'm using an AFHTTPRequestSerializer. Maybe, if I change it to AFJSONRequestSerializer it will fix the problem but I really don't want to since I have written many methods this way.

另外,我正在使用AFHTTPRequestSerializer。也许,如果我将其更改为AFJSONRequestSerializer,它将解决问题,但我真的不想,因为我已经用这种方式编写了很多方法。

3 个解决方案

#1


3  

"query string parameterization is simply not a reliable way of encoding nested data structures. This is why all modern web frameworks have built-in conveniences that automatically decode incoming JSON into parameters." - Mattt Thompson

“查询字符串参数化根本不是编码嵌套数据结构的可靠方法。这就是为什么所有现代Web框架都具有内置的便利,可以自动将传入的JSON解码为参数。” - 马特汤普森

So, JSON it is...

那么,JSON就是......

Parameters:

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

Send:

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);
          }];

Retrieve:

<?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);

?>

Response:

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

All done!

Pure gold.

#2


2  

update function AFQueryStringPairsFromKeyAndValue

更新函数AFQueryStringPairsFromKeyAndValue

change

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

to

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

#3


0  

Had the same issue with AFHTTPSessionManager. Unfortunately you have to switch to AFJSONRequestSerializer to send array of dictionaries:

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

manager.requestSerializer = [AFJSONRequestSerializer serializer];

AFJSONRequestSerializer sets application/json content-type and server that expects JSON will successfully accept request parameters while AFHTTPRequestSerializer will always have text/html content-type in header even if you set it explicitly.

AFJSONRequestSerializer设置application / json内容类型和服务器,期望JSON成功接受请求参数,而AFHTTPRequestSerializer在标头中始终具有text / html内容类型,即使您明确设置它也是如此。

#1


3  

"query string parameterization is simply not a reliable way of encoding nested data structures. This is why all modern web frameworks have built-in conveniences that automatically decode incoming JSON into parameters." - Mattt Thompson

“查询字符串参数化根本不是编码嵌套数据结构的可靠方法。这就是为什么所有现代Web框架都具有内置的便利,可以自动将传入的JSON解码为参数。” - 马特汤普森

So, JSON it is...

那么,JSON就是......

Parameters:

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

Send:

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);
          }];

Retrieve:

<?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);

?>

Response:

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

All done!

Pure gold.

#2


2  

update function AFQueryStringPairsFromKeyAndValue

更新函数AFQueryStringPairsFromKeyAndValue

change

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

to

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

#3


0  

Had the same issue with AFHTTPSessionManager. Unfortunately you have to switch to AFJSONRequestSerializer to send array of dictionaries:

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

manager.requestSerializer = [AFJSONRequestSerializer serializer];

AFJSONRequestSerializer sets application/json content-type and server that expects JSON will successfully accept request parameters while AFHTTPRequestSerializer will always have text/html content-type in header even if you set it explicitly.

AFJSONRequestSerializer设置application / json内容类型和服务器,期望JSON成功接受请求参数,而AFHTTPRequestSerializer在标头中始终具有text / html内容类型,即使您明确设置它也是如此。