2

从 iOS 5 和 OSX 10.7 及更高版本开始,使用 解析 JSON 非常容易,解析 JSON 时NSJSONSerialization将返回一个NSDictionaryNSArray(或可变变体,如果指定)。值被解析为常见的 Cocoa 类型,例如NSString,但是我很想知道在从or获取数据并将其解析为我的应用程序中的数据对象NSNumber时我需要多小心。我的主要担忧是密钥的值 a) 是否不是 nil 和 b) 是否不是意外类型。NSDictionaryNSArray

例如,假设我有以下 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"
   }
}

如果我的应用程序需要一个NSStringfor 键info,它会再次崩溃,因为会找到一个 NSDictionary。

在很大程度上,来自 API 或文件的大多数 JSON 都应该是健全的,并且受当前版本的应用程序支持,并且希望所有 JSON 都经过版本化并在服务器端正确编码。在某些情况下,如果 JSON 已损坏或修改,应用程序可能会崩溃,我想避免这种情况。

潜在的解决方案:

  • 检查每个键/值对是否为isKindOfClass:orrespondsToSelector:并且仅在为 true 时继续
  • 检查密钥是否存在,如果为零则产生错误
  • 将所有内容都包含在一个 try/catch 块中,但是我宁愿使用可以使用的内容,如果数据有问题,则会产生错误。这可能会导致很多 @try/@catch 语句相互包含

这些解决方案中的每一个都相当庞大,并且在我的代码中添加了很多我希望尽可能避免的代码(并且在使用“好”JSON 时,这是完全可能的)。如果有一个替代解决方案可以处理解析 JSON 的过程,在将其放入自定义对象之前检查键的类型和值,我很想知道。

4

2 回答 2

2

您通常应该针对稳定的 API 运行。您担心的更改应该伴随着任何合理系统中的版本号更改,这将使您的应用程序免受更改,直到适当的升级时间。因此,您通常应该知道预期的数据类型。

在某些情况下,API 将指定可以根据多重性接收字典或数组,类似这样。在这种情况下,您应该检查课程并采取相应措施。

你绝对应该检查nilNSNull优雅地处理这些。

解析器应处理损坏的 JSON,并向您返回适当的错误。

此外,您可以使用像 RestKit 这样的框架来为您映射到您的自定义对象。它作为标准进行大量数据类型检查,并且基本上将所有映射代码删除到一个简单的配置中。它还处理所有网络通信(通过 AFNetworking)。

于 2013-09-22T18:08:30.387 回答
0

您需要确保您的代码能够安全抵御黑客的攻击。当您从服务器请求 JSON 时,您必须期望数据不是来自您的服务器而是来自其他地方,并且其他人可能已经设计了返回的数据以造成最大的损害。现在,如果您收到字符串而不是数字,则崩溃是非常安全的。

您必须期望您对服务器的请求是由一些大脑受损的硬件来满足的,这些硬件试图“提供帮助”,例如当互联网连接失败时。您可能会收到一个“有用的”网站,而不是 JSON,该网站应该告诉用户如何重置他们的路由器。尝试使用某人的免费 WiFi 的用户可能有连接返回奇怪的结果。这通常对 JSON 没有问题,因为解析会失败(所以解析失败是您应该期望和处理的),如果您期望 html.

您必须期望您正在使用的公共 API 存在错误或意外行为,并且在发生这种情况时您应该表现良好。添加调试代码,这些代码至少会在您开发时记录任何意外情况。编写代码,使其适用于 API 显示的任何行为。

如果您使用自己的 API,您还应该记录任何意外情况,然后告诉服务器人员他们是否做了不应该做的事情。

于 2015-04-07T09:11:02.860 回答