在Swift中捕获NSJSONSerialization错误

11

我正在努力理解为什么我无法捕获NSJSONSerialization抛出的错误。

我期望捕获NSInvalidArgumentException异常,但是应用程序却崩溃了。

这在使用Xcode 8的Swift 3和Swift 2.3中都发生了。

Swift 3:

    do {
        _ = try JSONSerialization.data(withJSONObject: ["bad input" : NSDate()])
    }
    catch {
        print("this does not print")
    }

Swift 2.3:

    do {
        _ = try NSJSONSerialization.dataWithJSONObject(["bad input" : NSDate()], options: NSJSONWritingOptions())
    }
    catch {
        print("this does not print")
    }

这段代码需要放在一个空的 Xcode 项目中 applicationDidFinishLaunching 方法中。在模拟器和设备上都经过测试。

完整异常信息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSDate)'

有什么想法,为什么catch块没有捕获到这个特定的错误?


do/try/catch 捕捉的是 Swift 的错误,而非 Objective-C 的异常。 - dan
这是一个编程错误,应该会崩溃。 NSDate 不是一个有效的 JSON 类型。修复编程错误。 - rmaddy
我正在制作一个接受JSON对象作为参数的API,因此在编译时我不知道它将获得什么输入。看起来唯一的解决方案是桥接到Objective-C领域,在那里捕获异常。我还将研究使用isValidJSONObject - Erik Villegas
1
我就是不明白为什么所有我在网上看到的教程都使用 do/catch 模式。有没有任何 NSJSONSerialization 的错误会被 Swift 的 catch 块捕获? - Erik Villegas
1
所有的教程都使用try,因为dataWithJSONObject被声明为throws。不幸的是,文档非常模糊。关于“内部错误”的一些内容。但是使用isValidJSONObject是你想要的,因为它将避免NSInvalidArgumentException问题。无需桥接到Objective-C。 - rmaddy
1个回答

18

根据JSONSerialization data(withJSONObject:options:)文档:

如果obj无法生成有效的JSON,则会抛出异常。此异常在解析之前抛出,表示编程错误而非内部错误。在调用此方法之前,您应该通过使用isValidJSONObject(_ :)来检查输入是否会生成有效的JSON。

这意味着您无法捕获由无效数据引起的异常。只有“内部错误”(实际上是什么意思)可以在catch块中捕获。

为避免可能的NSInvalidArgumentException,您需要使用isValidJSONObject

因此,您的代码变为:

do {
    let obj = ["bad input" : NSDate()]
    if JSONSerialization.isValidJSONObject(obj) {
        _ = try JSONSerialization.data(withJSONObject: obj)
    } else {
        // not valid - do something appropriate
    }
}
catch {
    print("Some vague internal error: \(error)")
}

实际上会抛出什么样的错误?似乎我应该只使用带有JSONSerialization的try? - Michael Ozeryansky
@Michael 只有在您对修复编程错误没有兴趣时才使用 try? - rmaddy
消极是不生产的。 如果有其他人想知道,这里是显示所有可能错误的源:https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/JSONSerialization.swift - Michael Ozeryansky
1
@MichaelOzeryansky 我没有表现出否定的态度。你说应该使用try?,我明确表示你不想忽略错误。现有的答案显示了文档中解释为什么不应该忽略异常的引用。 - rmaddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接