NSMutableURLRequest带有参数 - 无法解析响应

3
我正在尝试创建到打印JSON代码的URL的连接,然后将其解析和处理。我的URL有一个名为“bypass”的参数。URL看起来像这样:http://www.getchanged.net/json.asp?bypass=MIGCBgkrBgEEAYI3WAOxxx。由于它总是显示“连接失败,错误:无法解析响应”,所以我没有成功解决这个问题。
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。


调试此类错误的最佳方法是设置断点并实际查看服务器返回的响应。通常,JSON解析失败是因为服务器返回带有HTML正文的500错误,如果是这种情况,您就知道请求是错误的。否则,如果服务器返回正确的结果,则可能是服务器格式化响应的方式存在问题。 - dirkgroten
5个回答

4
一些观察:
  1. 关键问题在于您正在发出一个 GET 请求,但是在请求的正文中提供了 bypass 参数。对于 POST 请求,应将参数添加到正文中,但对于 GET 请求,应将其添加到 URL 中。

  2. 如果此 bypass 键可能包含保留字符(例如空格、&+ 等),则应对您提供的 bypass 值进行百分比转义。如果可以保证它只包含字母数字,则可以不进行百分比转义,但通常情况下,您应始终对 HTTP 参数进行百分比转义。

  3. 虽然第1点可能解决此问题,但有时 Web 服务会期望设置某些头字段。例如,通常会设置请求的 Content-Type 头(例如,这似乎应该是请求的 Content-Typeapplication/x-www-form-urlencoded)。

  4. 您说您收到了一个错误消息“连接失败,错误为:无法解析响应”。您没有向我们展示生成此错误的代码,但我假设当您的代码尝试将响应解析为 JSON 时,它无法解析。

    在将来诊断这些问题时,我发现实际检查响应的详细信息很有用。值得注意的是,响应的头将包含在 NSURLResponse 中(它实际上将是一个 NSHTTPURLResponse,其具有可以非常说明性的 statusCode 数字值)。响应的正文通常是错误的字符串表示形式(通常当 Web 服务失败时,它会生成错误的文本或 HTML 描述)。

    在将来遇到此类错误时,始终查看服务器返回的 statusCode 和文本,因为这将帮助您诊断正在发生的情况。它比一般的“无法解析响应”消息更具信息量。

  5. 如果您拥有一个运行良好的 Web 接口和一个不工作的应用程序接口,则使用像 Charles 这样的工具观察 Web 浏览器生成的请求并将其与应用程序生成的请求进行比较有时很有用。在诊断这种问题时,这可能非常有价值。

    此外,如果您使用类似 Charles 的工具,则可以手动检查服务器的状态代码和文本响应,我建议您在第4点中以编程方式处理。


第一点对我很有帮助。谢谢。 - hasan

2

将请求的HTTPMethod更改为POST,问题就会解决。

@property (copy) 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];

这个网站确认了这是一个有效的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];

当我尝试两者时,我得到以下错误:Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x171a6cec0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} - nimrod
看起来像是JSON文本错误,哪一行引起的呢?无论如何,这里有一个参考项目 - gabbler
感谢您的项目。我也遇到了(null)。您能否检查正确的绕过哈希值?(MIGCBgkrBgEEAYI3WAOgdT) - nimrod

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字符串和字典,因为我不确定您想要什么。

我刚刚在答案中添加了一份包含NSMutableURLRequest的代码版本。 - mattr

1
除了Rob解决的问题之外,从列出的网站返回的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所述,任何字符串值都可以包含除“或\或控制字符以外的任何UNICODE字符。

因此,字符串值的结构如下:


enter image description here

请注意换行和回车所需的转义格式。
考虑到这一点,并查看在Charles中捕获的原始输出,您可以看到第26行第84列包含x0d后跟x0a(即旧的Windows样式CRLF)在值的中间。
服务器应该在发送这些值之前对它们进行转义处理。
顺便说一句,JSON中有很多空格(x20)和CRLF,位于数组、对象和值以外,在不影响JSON的情况下,这些都是不必要的并且会增加数据传输量。

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解析失败。 如果您不想共享该数据,可以使用虚拟数据编辑原始响应(不要替换特殊字符),并在此处共享,这将有助于所有人进行更多调试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接