NSJSONSerialization 不工作,NSUTF8StringEncoding 工作

Posted

技术标签:

【中文标题】NSJSONSerialization 不工作,NSUTF8StringEncoding 工作【英文标题】:NSJSONSerialization Not Working, NSUTF8StringEncoding Is Working 【发布时间】:2014-03-11 12:50:23 【问题描述】:

我已经阅读了文档、教程和其他 Stack Q&A,我很想知道如何使用 NSUTF8StringEncoding 让我的 JSON 出现,但不使用 NSJSONSerialization - 这就是我需要将数据提取到NSDictionaryNSArray。我认为这是从我的 URL 返回的 NSData 格式的问题?

编辑这里是错误:Error Domain=NSCocoaErrorDomain Code=3840“无法完成操作。(Cocoa 错误 3840。)”(垃圾结束。) UserInfo=0x8aabc30

NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.sampleURL.com"]
                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                      timeoutInterval:15.0];

NSMutableData* responseData = [NSMutableData dataWithCapacity: 0];

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 

    //this works, and have NSLog below
    responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"string %@", responseString);

    [responseData appendData:data];
    responseData = [[NSMutableData alloc] initWithData:data];

     //this is null in NSLog
    NSError * error;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data   options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:&error];

    NSLog(@"jsonDict dict %@",jsonDict); 

调试控制台:

 2014-03-11 07:41:58.233 WBPC[7845:a0b] string   "id":"a1","session":"General","name":"Exhibitor Setup Begins","startTime":"0900","details":"9am Exhibitor Hall","png":"image","speaker1":"Johnson","speaker2":"Nelson","speaker3":"""id":"b1","session":"General","name":"Conference Registration","startTime":"1000","details":"10am Noon Upper Level Lobby","png":"image","speaker1":"Jackson","speaker2":"","speaker3":""
 2014-03-11 07:41:58.236 WBPC[7845:a0b] jsonDict (null)

【问题讨论】:

NSMutableDictionary * json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &error];试试这个 我实际上尝试过那个(来自你们中的其他 Stack 帖子),但没有运气。我确信这是从 URL 返回的 JSON 的格式问题... @NamoNamo - 这是我从 NSJSONSerialization 收到的错误:错误域 = NSCocoaErrorDomain 代码 = 3840“操作无法完成。(可可错误 3840。)”(垃圾结束。)用户信息=0x8aabc30。谢谢。 【参考方案1】:

您在 'didReceiveData' 委托函数中完成这一切,这不是正确的位置。唯一应该存在的是:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
    [self.responseData appendData:data];

但在此之前,您应该在连接收到响应时初始化“self.responseData”:

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    if(self.responseData != nil) self.responseData = nil;
    self.responseData = [[NSMutableData alloc] init];

然后,您需要实现另一个名为“connectionDidFinishLoading”的委托函数,当调用此方法时,您的“responseData”将包含来自 JSON 的所有数据并准备好解析:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection 

     responseString = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];

     NSLog(@"string %@", responseString);

     NSError * error;
     NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:&error];

     NSLog(@"jsonDict dict %@",jsonDict); 

我希望这在某种程度上有所帮助。

【讨论】:

感谢分享。实际上,我确实使用了这些委托方法,我只是出于说明目的简化了我的示例。 除了上面已经显示的之外,在委托方法connection: didReceiveResponse: 中应该检查HTTP 状态代码和响应数据的类型(MIME 类型)。如果状态码指示错误,我们无论如何都应该读取响应,以便从服务器获取可能的“错误消息”。在connectionDidFinishLoading: 中,我们再次使用 HTTP 状态码来决定是否应该记录错误消息或根据 MIME 类型处理预期的响应数据。【参考方案2】:

您的 JSON 格式不正确。您告诉我们它是(为便于阅读而添加了空格和换行符):


    "id": "a1",
    "session": "General",
    "name": "Exhibitor Setup Begins",
    "startTime": "0900",
    "details": "9am Exhibitor Hall",
    "png": "image",
    "speaker1": "Johnson",
    "speaker2": "Nelson",
    "speaker3": ""

    "id": "b1",
    "session": "General",
    "name": "Conference Registration",
    "startTime": "1000",
    "details": "10am Noon Upper Level Lobby",
    "png": "image",
    "speaker1": "Jackson",
    "speaker2": "",
    "speaker3": ""

这在两个字典条目之间缺少逗号,并且您缺少应该包装 JSON 的 []。如果它真的是一个字典条目数组,它应该是:

[
    
        "id": "a1",
        "session": "General",
        "name": "Exhibitor Setup Begins",
        "startTime": "0900",
        "details": "9am Exhibitor Hall",
        "png": "image",
        "speaker1": "Johnson",
        "speaker2": "Nelson",
        "speaker3": ""
    ,
    
        "id": "b1",
        "session": "General",
        "name": "Conference Registration",
        "startTime": "1000",
        "details": "10am Noon Upper Level Lobby",
        "png": "image",
        "speaker1": "Jackson",
        "speaker2": "",
        "speaker3": ""
    
]

如果你想检查你的 JSON,你可以访问http://jsonlint.com。此外,如果您检查了 JSONObjectWithData 返回的 error 对象,它会为您指明正确的方向。

您应该看看这个 JSON 是如何生成的。看起来它必须是手动生成的。例如,如果您从 php 页面生成此文件,则应使用 json_encode,而不是手动生成 JSON。


顺便说一句,您正在尝试解析didReceiveData 中的结果。在connectionDidFinishLoading 之前,您不应该尝试解析。您的 didReceiveData 应该仅将 data 附加到您的 NSMutableData 对象。解析应该推迟到connectionDidFinishLoading

【讨论】:

问题在于我的 PHP 是如何输出 JSON 的,我需要将它包装在这样的数组中: $output = array();而 ($list = mysql_fetch_assoc($query)) $output[] = $list; echo json_encode($output);【参考方案3】:

你好,你可以试试这个。

NSError *error = nil;
NSArray *jsonResponseArray = [NSJSONSerialization JSONObjectWithData: YOURDATA options: NSJSONReadingMutableContainers error: &error];

if (!jsonResponseArray) 
  NSLog(@"Error: %@", error);
 else 
   for(NSDictionary *dic in jsonResponseArray) 
      NSLog(@"dic values are : %@", item);
   

谢谢

【讨论】:

不幸的是我也试过这个,但没有运气。【参考方案4】:

您发布的 JSON 字符串不是有效的 JSON。仅仅因为数据是有效的 UTF8 字符串并不意味着它一定是 JSON。尝试将调试后的字符串粘贴到 JSONLint 中,它会显示您的 JSON 对象之间缺少逗号。

【讨论】:

当然 JSON 可以是 UTF-16 或 UTF-32,所以有效的 JSON 不需要是有效的 UTF8 字符串。

以上是关于NSJSONSerialization 不工作,NSUTF8StringEncoding 工作的主要内容,如果未能解决你的问题,请参考以下文章

NSJSONSerialization 将 \n 添加到 JSON 字符串的开头和结尾

使用 NSJSONSerialization 解析 JSON - 抛出 NSException

NSJSONSerialization 不解析这个 JSON

NSJSONSerialization 不更新数据

NSJSONSerialization 不创建可变容器

NSJSONSerialization 不解析 NSManagedObject