32

I am using JSONDecoder() in Swift and need to get better error messages.

Within the debug description (for example) I can see messages like "The given data was not valid JSON", but I need to know it is that rather than a network error (for example).

let decoder = JSONDecoder()
if let data = data {
   do {
      // process data

   } catch let error {
      // can access error.localizedDescription but seemingly nothing else
   }
}

I tried to cast to a DecodingError, but this does not seem to reveal more information. I certainly don't need the string - even an error code is much more helpful than this...

4
  • You have to cast the error to specific type to access the properties. Check out documentation for more details. docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html Commented Mar 28, 2019 at 4:13
  • I know, I tried DecodingError. But it has no more detail than error alone. Commented Mar 28, 2019 at 4:16
  • Can you post the code you have tried? It will help us to get more context of your issue. Commented Mar 28, 2019 at 4:22
  • print ("Error in reading data", error as! DecodingError) print ("error", error.localizedDescription) let decerr = error as! DecodingError print (decerr.errorDescription) print ("resaon", decerr.errorDescription) Commented Mar 28, 2019 at 4:23

1 Answer 1

112

Never print error.localizedDescription in a decoding catch block. This returns a quite meaningless generic error message. Print always the error instance. Then you get the desired information.

let decoder = JSONDecoder()
if let data = data {
   do {
      // process data

   } catch  {
      print(error)
   }
}

Or for the full set of errors use

let decoder = JSONDecoder()
if let data = data {
    do {
       // process data
    } catch let DecodingError.dataCorrupted(context) {
        print(context)
    } catch let DecodingError.keyNotFound(key, context) {
        print("Key '\(key)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch let DecodingError.valueNotFound(value, context) {
        print("Value '\(value)' not found:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch let DecodingError.typeMismatch(type, context)  {
        print("Type '\(type)' mismatch:", context.debugDescription)
        print("codingPath:", context.codingPath)
    } catch {
        print("error: ", error)
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

localizedDescription should only be used if you need to display something to the end user.
I really like this answer. The only difference - for my own debugging -was omitting the context variable as it was too verbose. catch let DecodingError.keyNotFound(key, _) { print("[!]Key '\(key)' not found")
Can you get access to the property that was type mismatched? Say a field came back as an Int when I'm expecting a String, I want to set a default value for that property in that case
@infiltratingtree This makes no sense, because when an error occurs the decoding process will be interrupted and terminated.
Maybe I'm not explaining properly. I want to know which field caused the decoding error. Is there any way to get that info?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.