在iPhone中从URL检索JSON时确定问题

时间:2014-02-06 15:57:50

标签: ios objective-c json nsurlconnection nsstringencoding

首先我要说的是,我并不是特别想找到一个解决方案,而只是解决问题的根本原因。我正在尝试从网址中检索JSON。在浏览器中,url调用工作得很好,我能够看到整个JSON没有问题。但是,在简单使用NSURLConnection的x代码中,我获取数据字节,但我的NSString为空。

    theString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];

经过一些研究后我发现我可能正在尝试使用错误的编码。我不确定url正在使用什么类型的编码,所以在第一直觉我尝试了一些随机编码类型。

    NSString* myString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    NSString* myString2 = [[NSString alloc] initWithData:data encoding:NSUTF16StringEncoding];
    NSString* myString3 = [[NSString alloc] initWithData:data encoding:NSWindowsCP1252StringEncoding];

NSASCIIStringEncoding和NSWindowsCP1252StringEncoding能够恢复部分正确的JSON。它不是我能够在浏览器中查看的整个JSON,并且有些字符有点混乱,但它是一些东西。为了尝试更好地确定使用的编码,我决定使用以下方法通过查看返回的编码来尝试确定它。

NSError *error = nil;
NSStringEncoding encoding;
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
                                                 usedEncoding:&encoding
                                                        error:&error];

我的NSStringEncoding值是3221214344.每次运行应用程序时,此数字都是一致的。我找不到任何甚至接近匹配的NSStringEncoding值。

我的最后一个问题是:用于此网址的编码是否不能被iOS使用,是否可能为此网址使用了多种类型的编码,或者是否有其他我可能在我的网站上做错了?< / p>

2 个答案:

答案 0 :(得分:1)

即使看起来答案已在评论中提供(使用iso-8859-1作为正确的编码),我认为值得讨论如何调试此问题。

你说桌面浏览器(Chrome)可以正确地消化数据,所以让我们使用它:

  1. 启用开发人员工具https://developers.google.com/chrome-developer-tools/
  2. 当开发工具窗口打开时,切换到“网络”并在该浏览器选项卡中执行您的呼叫
  3. 点击请求网址检查输出 - 它应该给你一些线索。
  4. 如果这不起作用,Postman之类的工具可以帮助您在设备上实现之前重新创建呼叫

答案 1 :(得分:1)

如果可能的话,最好不要依赖Cocoa来计算字符串编码,尤其是在数据可能已损坏的情况下。更好的方法是检查HTTP Content-Type标头指示的值是否指定了一个字符集,如下例所示:

Content-Type: text/html; charset=ISO-8859-4

一旦您能够从Content-Type标头解析和检索字符集名称,您需要将其转换为NSStringEncoding,首先将其转换为CFStringConvertIANACharSetNameToEncoding,然后再传递返回的CF字符串编码为CFStringConvertEncodingToNSStringEncoding。之后,您可以使用-[NSString initWithData:encoding:]初始化字符串。

NSData *HTTPResponseBody = …; // Get the HTTP response body
NSString *charSetName = …;  // Get a charset name from the Content-Type HTTP header

// Get the Core Foundation string encoding
CFStringEncoding cfencoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)charSetName);

// Confirm this is a known encoding
if (cfencoding != kCFStringEncodingInvalidId) {
    // Initialize the string
    NSStringEncoding nsencoding = CFStringConvertEncodingToNSStringEncoding(cfencoding);
    NSString *JSON = [[NSString alloc] initWithData: HTTPResponseBody 
                                           encoding: nsencoding];
}

如果您使用的字符串数据已损坏,您仍可能遇到问题。例如,在上面的代码片段中,charSetName可能是UTF-8,但HTTPResponseBody无法解析为UTF-8,因为字节序列无效。在这种情况下,当你尝试实例化你的字符串时Cocoa将返回nil,并且没有清理数据以使其符合报告的字符串编码(可能通过去除无效的字节序列),你可能想要报告错误回到最终用户。

作为最后的努力 - 而不是报告错误 - 您可以使用可以处理您抛出的任何内容的编码来初始化字符串,例如NSMacOSRomanStringEncoding。这里需要注意的是,unicode / corrupted数据可能会间歇地显示为符号或意外的字母数字。