Как я могу ПОСТАВИТЬ NSArray NSDictionaries внутри NSDictionary без проблем?

Я знаю, как это сделать, это довольно просто.

Проблема в том, что это не работает.

Вот функция, которую я использую для размещения данных:

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

INSANE!

По какой-то причине он ломается, если я добавляю дополнительный атрибут.

Это должно быть AFNetworking ошибка, потому что это не имеет смысла.

РЕДАКТИРОВАТЬ:

Я мог бы:

  1. Сделайте два поля MySQL: websiteTitles, websiteURL.

  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 это решит проблему, но я действительно не хочу, так как я написал много методов таким образом.

4

Решение

«Параметризация строки запроса просто не является надежным способом кодирования вложенных структур данных. Вот почему все современные веб-фреймворки имеют встроенные удобства, которые автоматически декодируют входящий JSON в параметры».Мэтт Томпсон

Так, 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";
}

Все сделано!

Чистое золото.

3

Другие решения

функция обновления 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)];
}
2

Была такая же проблема с AFHTTPSessionManager,
К сожалению, вы должны переключиться на AFJSONRequestSerializer отправить массив словарей:

manager.requestSerializer = [AFJSONRequestSerializer serializer];

AFJSONRequestSerializer наборы Применение / JSON Тип содержимого и сервер, который ожидает, что JSON успешно примет параметры запроса, в то время как AFHTTPRequestSerializer всегда будет иметь текст / html content-type в заголовке, даже если вы установили его явно.

0