NSJSONSerialization 弄乱了结果 NSDictionary

Posted

技术标签:

【中文标题】NSJSONSerialization 弄乱了结果 NSDictionary【英文标题】:NSJSONSerialization messing up resulting NSDictionary 【发布时间】:2014-08-22 09:32:09 【问题描述】:

我在解析来自 Web 服务的 json 输出时遇到问题。我正在使用 NSJSONSerialization 将输出解析为 NSDictionary。还通过子类化 AFHTTPSessionManager 来使用 AFNetworking。现在响应序列化器是 AFHTTPResponseSerializer 它返回 NSData 这是我正在使用的代码:

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:&err];

非常简单。并且 err 对象为零,因此转换工作正常。

但是:我直接从网络服务得到的结果是这样的:

           "address":
           
               "address1": "Ivy House",
               "address2": "Sandy Lane",
               "city": "Rush",
               "postCode": null,
               "email": "notknown@whatever.com",
               "telephone": "18437584",
               "mobile": null,
               "smsAlert": null,
               "county": "Dublin",
               "country": "Ireland",
               "websiteAddress": "www.example.com"
           ,

打印dict的内容后得到的结果是这样的:

address =     
    address1 = "Ivy House";
    address2 = "Sandy Lane";
    city = Rush;
    country = Ireland;
    county = Dublin;
    email = "notknown@whatever.com";
    mobile = "<null>";
    postCode = "<null>";
    smsAlert = "<null>";
    telephone = 18437584;
    websiteAddress = "www.example.com";
;

问题是生成的 NSDictionary 没有双引号,因此将 NSDictionary 以 plist 格式保存到磁盘失败!

我也尝试过使用 AFJSONResponseSerializer,它返回 NSDictionary 但内容和上面一样!

问题出在哪里?

提前致谢。

【问题讨论】:

您的示例中缺少双引号只是因为这是打印 NSDictionary(甚至可能是 NSString)的方式。如果将此字典保存到属性列表失败,那么这是由于另一个原因(您可以使用[NSPropertyListSerialization dataWithPropertyList:format:options:error:] 中的error 进行跟踪。 我同意@Andrey。似乎 NSDictionary 描述没有为仅包含字母数字字符(没有分隔符)的字符串添加引号。 @Andrey 我无法保存到 plist,所以我无法再次尝试阅读。即使 URL 完全有效,writeToURL:atomically: 也会返回 NO。文档说如果返回为 NO 那么这是因为字典没有正确形成(此方法在写出之前递归地验证所有包含的对象都是属性列表对象(NSData、NSDate、NSNumber、NSString、NSArray 或 NSDictionary 的实例)文件,如果所有对象都不是属性列表对象,则返回 NO,因为结果输出不是有效的属性列表。) 您可以使用dataWithPropertyList:format:options:error: 找出错误。它与双引号无关。我认为那些nulls 可能是保存到 plist 失败的真正原因。 我使用了 propertyListWithData:options:format:error: 这是我得到的错误:Error Domain=NSCocoaErrorDomain Code=3840 "The operation could not be completed. (Cocoa error 3840.)" ( Unexpected character at line 1) UserInfo=0x8e81b20 NSDebugDescription=Unexpected character at line 1, kCFPropertyListOldStyleParsingError=操作无法完成。 (可可错误 3840。) 【参考方案1】:

这里的问题似乎根本与双引号无关。打印时,NSDictionary(以及其他 Foundation 对象)在不需要时(例如,当字符串中没有空格或特殊字符时)删除包含双引号的双引号。

现在,阻止您将NSDictionary 序列化为属性列表的可能问题是在 JSON 中存在 nulls,因此在 NSDictionary 中存在。根据documentation:

属性列表对象包括 NSDataNSStringNSArrayNSDictionaryNSDateNSNumber 对象。

而来自 JSON 的 nulls 将表示为 NSNull 的实例,从而使您的 NSDictionary 成为无效的属性列表。

【讨论】:

【参考方案2】:

NSDictionary 的结构与 JSON 字符串不同。因此,当您将 JSON 字符串解析为 NSDictionary 时,您不应该期望引号。

您可以保存 JSON 数据并在运行时再次对其进行解析。

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"yourfilename.dat"];

 // Save it into file system
[data writeToFile:dataPath atomically:YES];

【讨论】:

我回到使用 AFHTTPResponseSerializer 并且 responseObject 现在是 NSData 类型。这是我的代码: NSString *filePath = [[self applicationCacheDirectory] ​​stringByAppendingPathComponent:@"yourfilename.dat"]; BOOL save = [responseData writeToFile:filePath atomically:YES];立即保存返回 YES!我可以再次将数据文件读入 NSDictionary。所以这看起来是一个很好的解决方法

以上是关于NSJSONSerialization 弄乱了结果 NSDictionary的主要内容,如果未能解决你的问题,请参考以下文章

为啥 QTextBrowser 弄乱了我的 HTML 代码?

实体框架弄乱了行 ID

RecyclerView 在滚动时弄乱了子视图

UITextField 子类弄乱了adjustFontSizeToWidth

PageSpeed 模块弄乱了图像的比例

Perl 5.10 是不是把原型弄乱了?