NSJSONSerialization - "字符串解析期间文件的意外结束"

时间:2014-04-15 07:48:25

标签: ios json nsjsonserialization

在解析一些REST响应时,我遇到了一些有线问题。问题是,我无法重现它。有时它会发生,我在错误日志中没有相应的信息。

Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Unexpected end of file during string parse (expected low-surrogate code point
but did not find one).) UserInfo=0x157bddb0 {NSDebugDescription=Unexpected end of file during string parse (expected low-surrogate code point but did not find one).}


对不起,由于敏感的用户数据,我不允许从JSON-Response中提供任何信息(它只出现在一些内部帐户中,其中错误日志级别设置为低以检测这个问题)。


其他一些信息:

  • JSON有效(通过http://jsonlint.com/检查)
  • 当尝试重现此问题时,我会收到其他NSError描述,例如:
    • XYZ位置的字符无效
    • 无效对象
    • ...



更新1:解析机制(NSData扩展)

- (NSDictionary *)objectFromJSONDataWithError:(NSError **)error {
    NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData: self
                                                               options: 0
                                                                 error: error];

    return jsonObject;
}



更新2:用于下载数据的NSOperation - main()的内容 - >更新1中的调用功能

NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = nil;

for (NSInteger i=0; i<kMaxRequestRetry; i++) {
    data = [NSURLConnection sendSynchronousRequest: request
                                 returningResponse: &response
                                             error: &error];

    if (!error) {
        // Handling internal errors and retry mechanism
    }

    [NSThread sleepForTimeInterval:1.0];
}

// Check http status code
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode < 200 || statusCode >= 300) {
    CLogWarn(@"Request finished with status code = %d", (int)statusCode);
}

// Evaluate response
if (error) {
    CLogError(@"%@", error);
    [self requestFinishedWithResult:@"{\"errorCode\":99}";
    return;
} else {
    NSError *parseError = nil;
    NSDictionary *responseDic = [data objectFromJSONDataWithError:&parseError];

    // Detect parse issues
    if (parseError) {
        CLogError(@"JSONParse-Error: %@", parseError);
        [self requestFinishedWithResult:[NSString stringWithFormat:@"{\"errorCode\":%d}", (11000 + (int)parseError.code)]];
        return;
    }

    // Success handling
}



更新3: JSON-Object结构

{
  "errorCode": 0,
  "conversations": [
      {
          "address": "+43664000000",
          "snippet": "This is an dummy text",
          "messagesUnread": 1,
          "messagesUnsent": 2,
          "messages": 9,
          "maxMessageId": 151672,
          "dateLastMessage": 1386353756858
      }
  ]
}



我很高兴有任何信息或提示如何强制使用此错误代码。

最诚挚的问候,
克里斯

2 个答案:

答案 0 :(得分:5)

问题再现

此问题的原因是string中的json包含非法的Unicode Point。以下代码可以重现此问题。

NSString* test = @"{\"\\ud801\" : 1}";
NSError* error = nil;
id result = [NSJSONSerialization JSONObjectWithData:[test dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
NSLog(@"error: %@", error);

<强>解决方案

根据Readme.md in JSONKit,您可以使用JSONKit作为额外的解析器。 e.g。

 id result = [NSJSONSerialization JSONObjectWithData:data options:options error:&error];
 if (error) {          
     error = nil;
     result = [data objectFromJSONDataWithParseOptions:JKParseOptionLooseUnicode error:& error];   // use JSONKit
 }

答案 1 :(得分:1)

发现了这个问题。 json对象中的“片段”包含原始消息的子字符串。我们的API(用java编写)使用substring方法和代理对的这种切割。 android和Windows客户端对此没有任何问题,只显示一个无效的char,但是NSJSONSerialization会抛出此错误。

通过apple dev论坛获得提示:https://devforums.apple.com/message/961738#961738