Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching NSJSONSerialization errors in Swift

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?

like image 477
Erik Villegas Avatar asked Nov 06 '16 15:11

Erik Villegas


People also ask

Do catch with error Swift?

Handling Errors Using Do-Catch. You use a do - catch statement to handle errors by running a block of code. If an error is thrown by the code in the do clause, it's matched against the catch clauses to determine which one of them can handle the error.

Do catch vs try catch Swift?

do – This keyword starts the block of code that contains the method that can potentially throw an error. try – You must use this keyword in front of the method that throws. Think of it like this: “You're trying to execute the method.

What is error handling in Swift?

There are four ways to handle errors in Swift: — You can propagate the error from a function to the code that calls that function. — Handle the error using a do - catch statement. — Handle the error as an optional value (try?).


1 Answers

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)")
}
like image 160
rmaddy Avatar answered Oct 06 '22 02:10

rmaddy