2014-10-29 3 views
3

Я пытаюсь создать соединение с URL-адресом, который выводит код JSON, который затем анализируется и обрабатывается. У моего URL есть параметр bypass. URL выглядит следующим образом:NSMutableURLRequest с параметром - не удается разобрать ответ

http://www.getchanged.net/json.asp?bypass=MIGCBgkrBgEEAYI3WAOxxx

мне не удалось решить эту проблему, поскольку она всегда говорит Connection failed with error: cannot parse response

NSURL *aUrl = [NSURL URLWithString:@"http://www.getchanged.net/json.asp"]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 

[request setHTTPMethod:@"GET"]; 
NSString *postString = @"bypass=MIGCBgkrBgEEAYI3WAOxxx"; 
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]]; 

Ошибка:

2014-10-29 21:43:39.529 TestMap[57987:1931535] Connection failed with error: cannot parse response 

Что здесь не так?

Пожалуйста, обратите внимание: я заменил обходную окрошку немного, потому что он содержит разумные данные. Сайт работает и распечатывает выход JSON.

+0

Лучший способ отладки такого рода ошибок - установить точки останова и фактически посмотреть на ответ, который сервер дает вам. Часто разбор JSON терпит неудачу, потому что сервер возвращает ошибку 500 с телом HTML, если это тот случай, когда вы знаете, что ваш запрос неверен. В противном случае, если сервер вернет правильный результат, может возникнуть проблема в том, как сервер форматирует ответ – dirkgroten

ответ

1

Помимо вопроса хорошо адресованного Роба, то JSON возвращение из перечисленных веб-сайта не проверяет:

Я попробовал несколько валидаторов с URL и обводным хэшем (вы вывесили в комментариях) и JSON недействителен. Типичная ошибка возвращается:

JSON Content: Invalid JSON at line 26, column 84 
    Parse error on line 26: 
    ...rtragen", "adresse":"fairtragen - GmbH 
    -----------------------^ 
    Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined' 

Как объяснена в json.org любом значение строки может содержать

any UNICODE character except " or \ or control character

Таким образом, значениестроки имеет как структуру, как это:

enter image description here

Примечание к escape-формат, необходимый для новых строк и возврата каретки.

Принимая это во внимание, и, глядя на сырой продукции, захваченной в Charles вы можете увидеть, что строка 26, столбец 84 содержит x0d с последующим x0a (т.е. старого стиля окна CRLF) в середине значения.

Сервер должен избегать этих значений перед их отправкой.

Кстати, у JSON есть много пробелов (x 20) и CRLF вне, вне массива, объекты и значения, которые, хотя и не влияют на JSON, не нужны и накладывают большие объемы передачи данных.

2

Сменить запрос HTTPMethod на номер POST, все будет в порядке.

@property (копия) NSData * HTTPBody;

@discussion This data is sent as the message body of the request, as 
in done in an HTTP POST request. 

Вы также можете использовать GET таким образом, установить весь URL в качестве URL запроса и не установить HTTPBody.

NSString *urlAsString = @"http://www.getchanged.net/json.asp"; 
urlAsString = [urlAsString stringByAppendingString:@"?bypass=MIGCBgkrBgEEAYI3WAOxxx"]; 
NSURL *aUrl = [NSURL URLWithString:urlAsString]; 

Этого site подтвердил это допустимая строка JSON, однако в нем есть некоторые "\r\n", этот код, кажется, быть в состоянии решить эту проблему путем удаления "\r\n" из строки.

NSString* receivedString = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding]; 
receivedString = [receivedString stringByReplacingOccurrencesOfString:@"\r\n" withString:@""]; 

NSData *data = [receivedString dataUsingEncoding:NSUTF8StringEncoding]; 
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
+0

Когда я пытаюсь выполнить оба варианта, я получаю: «Ошибка домена = NSCocoaErrorDomain Code = 3840» Операция не может быть выполнена. (Ошибка Cocoa 3840.) "(текст JSON не начинался с массива или объекта и не позволял фрагментам не задаваться.) UserInfo = 0x171a6cec0 {NSDebugDescription = текст JSON не начинался с массива или объекта и не позволял фрагментам не задаваться.} ' – doonot

+0

Похож на текстовую ошибку JSON, какая строка вызывает ее? В любом случае, здесь [проект] (https://www.dropbox.com/s/egt2kvghezipu70/TestConnection.zip?dl=0) для справки. – gabbler

+0

Спасибо за проект. Я также получаю (null) с ним. Вы можете проверить правильность байпаса? (MIGCBgkrBgEEAYI3WAOgdT) – doonot

2

Я думаю, что это то, что вы хотите:

NSString * bypassId = @"MIGCBgkrBgEEAYI3WAOxxx"; 
NSURL *aUrl = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.getchanged.net/json.asp?bypass=%@",bypassId]]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
    NSString *jsonAsString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
    NSLog(@"string: %@",jsonAsString); 
    NSDictionary *jsonAsObject = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: nil]; 
    NSLog(@"dict: %@",jsonAsObject); 
}] resume]; 

Это печатает (в консоли):

2014-11-06 17:09:21.659 ] string: 
{"stores":[ 

]} 

2014-11-06 17:09:21.659 ] dict: { 
    stores =  (
    ); 
} 

Я его печать данных в виде строки JSON и словарь потому что я не совсем уверен, чего вы хотите.

+0

jast добавил версию кода к ответу, который имеет NSMutableURLRequest – mattr

+0

Удивительный человек .. Большое спасибо ... –

4

Несколько наблюдений:

  1. Ключевой вопрос заключается в том, что вы выдачи GET запрос, но поставлять параметр bypass в теле запроса. Для запросов POST параметры должны быть добавлены в тело, но для GET запросов он должен быть добавлен в URL-адрес.

  2. Если bypass ключ может либо содержать зарезервированные символы (например, пробелы, &, + и т.д.), вы хотите, чтобы процент-бежать значение, которое вы для подачи bypass. Если вам гарантировано, что он будет только буквенно-цифровым, вы можете уйти без процентов, избегая его, но, как правило, вы всегда должны избегать HTTP-параметров.

  3. Хотя точка № 1, вероятно, решит эту проблему, иногда веб-службы ожидают, что определенные поля заголовка будут установлены. Например, обычно задается заголовок Content-Type запроса (например, это выглядит так: Content-Type запроса должно быть application/x-www-form-urlencoded).

  4. Вы говорите, что получаете сообщение об ошибке: «Ошибка соединения с ошибкой: невозможно разобрать ответ». Вы не показали нам код, создающий эту ошибку, но я предполагаю, что это было сгенерировано, когда ваш код попытался разобрать ответ как JSON, когда он не был.

    В будущем, при диагностировании этих проблем, я считаю полезным на самом деле изучить детали ответа. Примечательно, что заголовок ответа будет содержаться в NSURLResponse (который фактически будет NSHTTPURLResponse, который имеет числовое значение statusCode, которое может быть очень хорошо освещено). Тело ответа часто будет строковым представлением ошибки (часто, когда веб-служба терпит неудачу, он генерирует текст или описание HTML ошибки).

    Всякий раз, когда вы получаете такие ошибки в будущем, всегда смотрите на statusCode и текст того, что возвращал сервер, так как это поможет вам определить, что происходит. Это будет более информативным, чем общее сообщение «Я не могу разобрать ответ».

  5. Если у вас есть веб-интерфейс, который работает, и интерфейс приложения, который этого не делает, иногда полезно использовать инструмент, например Charles, для наблюдения за запросом, созданным веб-браузером, и сравнить его с запросом, созданным приложение. Это может быть бесценным при диагностике подобных проблем.

    Кроме того, если вы используете что-то вроде Charles, это позволяет вручную проверять код состояния и текстовый отклик сервера, который я предположил, что вы можете обращаться программно в пункте №4.

+0

Точка помогла мне. благодаря – hasan83

0

Следующие работает отлично:

NSURL *aUrl = [NSURL URLWithString:@"http://www.getchanged.net/json.asp?bypass=MIGCBgkrBgEEAYI3WAOxxx"]; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 
    [request setHTTPMethod:@"GET"]; 

    NSURLResponse *response = nil; 
    NSError *error = nil; 
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
    if (!error) { 
     NSLog(@"Response String : %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 

     id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
     NSLog(@"Parsed Data : %@", json); 

    } 

Но это может случиться, что - как вы упомянули в своем Примечание - перепускной хэш изменяется, чтобы скрыть свои чувственные данные, эти данные могут иметь некоторые специальные символы или недействительный JSON, что не удается выполнить разбор JSON. Если вы не хотите делиться этими данными, вы можете редактировать исходный ответ с помощью фиктивных данных (не заменяйте специальные символы) и делиться ими, что поможет всем отлаживать больше.

Смежные вопросы