从 iOS 5 和 OSX 10.7 及更高版本开始,使用 解析 JSON 非常容易,解析 JSON 时NSJSONSerialization
将返回一个NSDictionary
或NSArray
(或可变变体,如果指定)。值被解析为常见的 Cocoa 类型,例如NSString
,但是我很想知道在从or获取数据并将其解析为我的应用程序中的数据对象NSNumber
时我需要多小心。我的主要担忧是密钥的值 a) 是否不是 nil 和 b) 是否不是意外类型。NSDictionary
NSArray
例如,假设我有以下 JSON 对象:
{
"version":1,
"title":"Some interesting title",
"info":"Some detail here"
}
目前,这将被解析为 NSDictionary:
@{
@"version": @1,
@"title":@"Some interesting title",
@"info": @"Some detail here"
}
我的问题是在检查我返回的数据类型时我应该多小心。从理论上讲,如果我使用了一个好的 API,我应该总是得到一个版本键的数值,但是如果由于某种原因它被更改为服务器端如下:
{ "version:"1", ... }
甚至更糟:
{ "version:"one", ... }
如果我尝试以下代码,我会遇到异常并且我的应用程序会崩溃:
NSNumber * myNumber = dictionary[@"version"];
if ([myNumber isEqualToNumber:@1])
{
...
}
代码不会执行,因为 a)dictionary[@"version"]
将是一个 NSString 并且 b) isEqualToNumber: 仅在 NSNumber 上可用(无法识别的选择器异常,应用程序会崩溃)。
同样,如果“信息”的 JSON 更改为以下内容,可能会出现问题:
{
"info":{
"code":200,
"message":"Some detail here"
}
}
如果我的应用程序需要一个NSString
for 键info
,它会再次崩溃,因为会找到一个 NSDictionary。
在很大程度上,来自 API 或文件的大多数 JSON 都应该是健全的,并且受当前版本的应用程序支持,并且希望所有 JSON 都经过版本化并在服务器端正确编码。在某些情况下,如果 JSON 已损坏或修改,应用程序可能会崩溃,我想避免这种情况。
潜在的解决方案:
- 检查每个键/值对是否为
isKindOfClass:
orrespondsToSelector:
并且仅在为 true 时继续 - 检查密钥是否存在,如果为零则产生错误
- 将所有内容都包含在一个 try/catch 块中,但是我宁愿使用可以使用的内容,如果数据有问题,则会产生错误。这可能会导致很多 @try/@catch 语句相互包含
这些解决方案中的每一个都相当庞大,并且在我的代码中添加了很多我希望尽可能避免的代码(并且在使用“好”JSON 时,这是完全可能的)。如果有一个替代解决方案可以处理解析 JSON 的过程,在将其放入自定义对象之前检查键的类型和值,我很想知道。