I'm trying to understand why I'm unable to catch the errors thrown by NSJSONSerialization.
I expect the NSInvalidArgumentException
exception to be raised and caught, but instead the app crashes.
This is occurring in both Swift 3 and Swift 2.3 using Xcode 8.
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")
}
This code is put in applicationDidFinishLaunching
inside a blank Xcode project. Tested on both simulator and device.
Full exception:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSDate)'
Any ideas why the catch block is not catching this particular error?
From the documentation for JSONSerialization data(withJSONObject:options:)
:
If obj will not produce valid JSON, an exception is thrown. This exception is thrown prior to parsing and represents a programming error, not an internal error. You should check whether the input will produce valid JSON before calling this method by using isValidJSONObject(_:).
What this means is that you can't catch the exception caused by invalid data. Only "internal errors" (whatever that actually means) can be caught in the catch
block.
To avoid a possible NSInvalidArgumentException
you need to use isValidJSONObject
.
Your code then becomes:
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)")
}