18

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.

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48

1 Answers1

15

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.

Community
  • 1
  • 1
Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
  • 3
    This doesn't answer the question "under what circumstances does JSONSerialization throw an error". I would extend the question and ask "What errors does JSONSerialization throw". Thus far, I haven't seen this anywhere in the class documentation. – BTRUE Apr 03 '17 at 07:11
  • 1
    I think you may be confusing exception and error. The crash is happening because an exception is being raised. If the method was throwing an error, it would be catchable. They are two different things. What I, and I thought you, were trying to find out is, what errors can the method throw, and when does it throw them. You're seeing the exception, not an error. – BTRUE Apr 04 '17 at 23:35
  • The first sentence of the answer, and the sample code, demonstrate an exception. (Note the `catch` in the sample code.) The last paragraph of the answer covers the crash mentioned in the question, which is caused by a different condition. I'll update the answer to clarify this. – Paul Cantrell Apr 05 '17 at 03:46