Paul Cantrell
Paul Cantrell

Reputation: 9324

Under what circumstances does JSONSerialization.data(withJSONObject:) throw a catchable error?

JSONSerialization.data(withJSONObject:options:) (aka dataWithJSONObject in Swift 2) is declared throws. However, passing invalid objects causes a crash, not a catchable error:

do  {
    // Crash
    try JSONSerialization.data(
        withJSONObject: NSObject(),
        options: [])
    }
catch
    {
    // Never reached
    print("Caught error:", error)
    }

Why is that method declared “throws,” then? Under what circumstances does it throw an exception?

Not knowing what causes an error to be thrown makes it hard to know how to handle the error, and makes it impossible to write tests that verify that handling.

Upvotes: 21

Views: 2831

Answers (1)

Paul Cantrell
Paul Cantrell

Reputation: 9324

Turns out it’s the same situation as this question: you can create a Swift string that contains invalid unicode (what?!), and that causes an exception.

let bogusStr = String(
    bytes: [0xD8, 0x00] as [UInt8],
    encoding: String.Encoding.utf16BigEndian)!

do  {
    let rawBody = try JSONSerialization.data(
        withJSONObject: ["foo": bogusStr], options: [])
    }
catch
    {
    // Exception lands us here
    print("Caught error:", error)
    }

Why does the example code in the original question crash, then, instead of also throwing an error?

Replying to a bug report, Apple informed me that you should call JSONSerialization.isValidJSONObject(_:) before data(withJSONObject:) if you don’t know for sure that the object is encodable, failing to do that is a misuse of the API, and that’s why they decided it should crash instead of throwing something catchable.

Upvotes: 16

Related Questions