带参数的 NSMutableURLRequest - 无法解析响应
Posted
技术标签:
【中文标题】带参数的 NSMutableURLRequest - 无法解析响应【英文标题】:NSMutableURLRequest with parameter - cannot parse response 【发布时间】:2014-10-29 20:46:37 【问题描述】:我正在尝试创建与打印出 JSON 代码的 URL 的连接,然后对其进行解析和处理。我的 URL 有一个名为 bypass
的参数。网址如下所示:
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 输出。
【问题讨论】:
调试此类错误的最佳方法是设置断点并实际查看服务器给您的响应。 JSON 解析通常会失败,因为服务器返回带有 html 正文的 500 错误,如果在这种情况下您知道您的请求是错误的。否则,如果服务器返回正确的结果,则可能是服务器格式化响应的方式有问题 【参考方案1】:几个观察:
关键问题是您发出GET
请求,但在请求正文中提供bypass
参数。对于POST
请求,参数应该添加到body中,但是对于GET
请求,它应该添加到URL中。
如果此 bypass
键可能包含保留字符(例如空格、&
、+
等),则您需要对为 @ 提供的值进行百分比转义987654329@。如果您保证它只是字母数字,您可以不用百分比转义它,但作为一般规则,您应该始终对 HTTP 参数进行百分比转义。
虽然第 1 点可能会解决此问题,但有时 Web 服务会期望设置某些标头字段。例如,通常设置请求的标头Content-Type
(例如,这看起来像请求的Content-Type
应该是application/x-www-form-urlencoded
)。
您说您收到一条错误消息,“连接失败并出现错误:无法解析响应”。您尚未向我们展示产生此错误的代码,但我认为这是在您的代码尝试将响应解析为 JSON 时生成的。
以后在诊断这些问题时,我发现实际检查响应的详细信息很有用。值得注意的是,响应的标头将包含在NSURLResponse
中(实际上是NSHTTPURLResponse
,它有一个statusCode
数值,可以非常有启发性)。响应的主体通常是错误的字符串表示形式(通常当 Web 服务失败时,它会生成错误的文本或 HTML 描述)。
以后每当您遇到此类错误时,请始终查看statusCode
和服务器返回的任何文本,因为这将帮助您诊断正在发生的事情。它将比一般的“我无法解析响应”消息提供更多信息。
如果您的 Web 界面可以正常工作,而应用程序界面不能正常工作,有时使用Charles 之类的工具来观察 Web 浏览器生成的请求并将其与应用程序。这在诊断这类问题时非常有用。
此外,如果您使用 Charles 之类的东西,这允许您手动检查服务器的状态代码和文本响应,我建议您可以在第 4 点中以编程方式处理。
【讨论】:
第一点帮助了我。谢谢【参考方案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];
【讨论】:
当我尝试两者时,我得到: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.
看起来像 JSON 文本错误,是哪一行导致的?无论如何,这里是project 供参考。
感谢您的项目。我也得到(空)它。您可以检查正确的绕过哈希吗? (MIGCBgkrBgEEAYI3WAOgdT)【参考方案3】:
我想这就是你想要的:
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 的答案【参考方案4】:除了 Rob 很好解决的问题之外,来自所列网站的 JSON 返回没有验证:
我已经使用 URL 和绕过哈希(您在 cmets 中发布)尝试了几个验证器,但 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 字符
所以 字符串值 具有如下结构:
注意换行符和回车所需的转义格式。
考虑到这一点,并查看在Charles 中捕获的原始输出,您可以看到第 26 行第 84 列在价值。
服务器应该在发送这些值之前对其进行转义。
顺便说一句,JSON 在数组、对象和值之外有很多空格 (x20
) 和 CRLF,虽然不会影响 JSON,但它们是不必要的,并且会增加数据传输。
【讨论】:
【参考方案5】:以下工作正常:
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 解析失败。 如果您不想共享该数据,您可以使用虚拟数据编辑原始响应(不要替换特殊字符),并在此处共享,这将有助于大家进行更多调试。
【讨论】:
以上是关于带参数的 NSMutableURLRequest - 无法解析响应的主要内容,如果未能解决你的问题,请参考以下文章
如何在上传带参数的图像时使用 AFNetworking 2.0 设置 cookie?
无法使用类型为“(NSMutableURLRequest,(_,_,_) throws -> _)”的参数列表调用“dataTaskWithRequest”