【问题标题】:Error parsing JSON string with Swift使用 Swift 解析 JSON 字符串时出错
【发布时间】:2014-07-18 22:01:34
【问题描述】:

我正在使用 Swift 来解析 JSON 字符串。这是代码:

var jsonStr = "..." // JSON string
var data = jsonStr.dataUsingEncoding(NSUTF8StringEncoding)
var error: NSError?
var array = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as [AnyObject]

而且这段代码几乎一直有效。但是今天我试图解析一个新的字符串输入,但它在最后一行使我的应用程序崩溃了。我什至看不到“错误”变量中的错误消息......它在该变量更新错误信息之前崩溃了。

我要解析的 JSON 字符串在这里:http://pastebin.com/wf6jtNhf

我确信我的 JSON 字符串有效有两个原因:

  • 我使用 jsonlint.com 验证了输入
  • 我创建了上面代码的 Objective-C 版本,它成功解析了相同的输入

谁能看到我无法解析这个字符串的原因,或者我应该假设 NSJSONSerialization 类在 Swift 中存在错误?我正在使用 Xcode Beta 3。

编辑 1:

显然我的字符串中有很多 UTF-16 字符(表情符号字符)。是否有解析保留这些字符的字符串的键?我试过NSUTF16StringEncoding下面的代码,但是没有用:

var data = jsonStr.dataUsingEncoding(NSUTF16StringEncoding)

编辑 2:

我在 Apple 开发者论坛上发布了同样的问题,当数据中有表情符号字符时,NSJSONSerialization.JSONObjectWithData() 的 Swift 版本中确实存在错误。我希望这在最终版本中得到解决。

此外,将我的变量从 [AnyObject] 更改为 as? Dictionary,如下面的一些建议,我的应用程序不再崩溃。

【问题讨论】:

  • 有没有人意识到超过一半的快速问题是关于解析 JSON 或 XML 的?
  • 在这种情况下,看起来您的 JSON 将返回字典而不是数组。
  • @JackWu 这是 [AnyObject] 的数组,所以没关系。我之前用 [AnyObject] 解析了类似的复杂 JSON,它运行良好,我认为这不是问题。此外,我上面代码的 Objective-C 版本正在将结果发送到 NSArray 并且它也能正常工作。不过,感谢您的快速回复。
  • 尝试在上面调用NSJSONSerialization.isValidJSONObject,它返回true吗?
  • 另外,它在 Swift 中也很重要,它是强类型的。您的 JSON 的顶级对象不是数组。 JSONObjectWithData:options:error: 返回一个 Foundation Object,在这种情况下它看起来像一个字典。尝试将其转换为字典,看看它是否仍然崩溃

标签: json swift


【解决方案1】:

在我的电脑上测试这个,你崩溃了,因为你正在投射as [AnyObject],并且你得到了一个 nil 结果。如果您将其更改为 as? [AnyObject],那么它将允许返回值可以为空,然后您就可以打印错误。

至于解析失败的原因,我还不太确定。罪魁祸首似乎是下面的块,不知道为什么它是无效的,也许是某些 UTF 给出了解析代码的问题。

"id": "@babiminkah",
               "nome": "B\u00E1rbara Santos",
               "imagem": "http://pbs.twimg.com/profile_images/490247572175327233/w4dXqfPm_bigger.jpeg",
               "texto": "amanh\u00E3 tem b\u00F3 do catarina..... na friends \uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02\uD83D\uDE02\uDE02",
               "horario": "2014-07-18 17:43:04"
               }

Edit1:从该块中提取更多部分,导致问题的是 texto 字段的值。如果您在\uD83D 之后(包括\uD83D)删除所有值,它将起作用。这些 un​​icode 值似乎是问题所在。

Edit2:据此,http://www.fileformat.info/info/unicode/char/d83d/index.htm、D83D 不是有效的 Unicode 字符。似乎后面的一些也不是。

【讨论】:

  • 谢谢,天空!我现在按照您的建议使用as? [AnyObject],它不再使我的应用程序崩溃,但error 仍然为零。无论如何,您似乎对 unicode 字符是正确的,但我想知道为什么 Objective-C 版本的代码可以毫无问题地解析 JSON...
  • 你是最棒的。我刚刚发现 D83D 是一个愚蠢的表情符号字符......我会在解析 JSON 之前尝试从字符串中删除它。有趣的是,正如我之前所说,Objective-C 版本的 NSJSONSerialization 可以解析该字符串……显然 Swift 版本还不能做到这一点。再次感谢!
  • \uD83D 是编码平面 1 字符的代理对的第一个大厅,这对是: \uD83D\uDE02 编码?。但是每对之后都有一个额外的 \uDE02 ,因此编码不正确。请参阅UTF-16 代码点 U+010000 到 U+10FFFF。 Unicode 是 21 位编码,但直到最近添加表情符号后,所有字符都可以编码为 16 位。
  • 您确实需要创建一个新问题。我想看到的主要是作为十六进制转储的实际数据。 NSData 的 NSLog 可以工作。我会使用 Charles Proxy 查看从服务器返回的原始十六进制数据。
猜你喜欢
  • 1970-01-01
  • 2017-08-27
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多