Robert
Robert

Reputation: 1192

Passing JSON Decode error into something actionable

I'm trying to improve my error handling when I don't get back any data in my JSON. The function below works fine without any issues except if I catch an error. I'm not sure of how to pass the error to prompt the user or is the way to handle the error if googlebusinessinfo is nil I likely have no data and pass a generic error?

Here's my function:

    func getBusinessReviews(googleUrl: String, completion: @escaping (WelcomeReview?) -> ()) {
    // Create URL
    let url = URL(string: googleUrl)
    guard let requestUrl = url else { fatalError() }
    // Create URL Request
    var request = URLRequest(url: requestUrl)
    // Specify HTTP Method to use
    request.httpMethod = "GET"
    //Set HTTP Header

    // Send HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        // Specify HTTP Method to use
        request.httpMethod = "GET"
        print("(Google)Do we have any data: \(String(describing: data))")
        // Check if Error took place
        if let error = error {
            print("Error took place \(error)")
            return
        }

        // Read HTTP Response Status code
        if let response = response as? HTTPURLResponse {
            print("(Google)Response HTTP Status code: \(response.statusCode)")
        }

        // Convert HTTP Response Data to a simple String
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("Googledata Response data string:\n \(dataString)")
        }

        if let googlebusinessdata = data {
            do {
                let googlebusinessinfo = try JSONDecoder().decode(WelcomeReview.self, from: googlebusinessdata)
                print("googledata \(googlebusinessinfo)")
                completion(googlebusinessinfo)
            } catch
            {
                print("googledata error \(error.localizedDescription)")
                let googebusinessinfoerror = error.localizedDescription
            }
        }
    }
    task.resume()
}

Upvotes: 0

Views: 129

Answers (1)

vadian
vadian

Reputation: 285082

First of all you can improve the error handling immensely if you print error instead of error.localizedDescription in a Decoding catch block. The former shows the real error, the latter a meaningless generic message.

To answer your question use the generic Result type

func getBusinessReviews(googleUrl: String, completion: @escaping (Result<WelcomeReview,Error>) -> ()) {
    // Create URL
    let url = URL(string: googleUrl)
    guard let requestUrl = url else { fatalError() }
    // Create URL Request
    var request = URLRequest(url: requestUrl)
    // Specify HTTP Method to use
    request.httpMethod = "GET"
    //Set HTTP Header

    // Send HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        // Specify HTTP Method to use
        request.httpMethod = "GET"
        print("(Google)Do we have any data: \(String(describing: data))")
        // Check if Error took place
        if let error = error {
            print("Error took place \(error)")
            completion(.failure(error))
            return
        }

        // Read HTTP Response Status code
        if let response = response as? HTTPURLResponse {
            print("(Google)Response HTTP Status code: \(response.statusCode)")
        }

        // Convert HTTP Response Data to a simple String
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("Googledata Response data string:\n \(dataString)")
        
            do {
                let googlebusinessinfo = try JSONDecoder().decode(WelcomeReview.self, from: data)
                print("googledata \(googlebusinessinfo)")
                completion(.success(googlebusinessinfo))
            } catch
            {
                print("googledata error:", error)
                let googebusinessinfoerror = error.localizedDescription
                completion(.failure(error))
            }
        }
    }
    task.resume()
}

and call it

getBusinessReviews(googleUrl: "Foo") { result in
    switch result {
        case .success(let info): print(info)
        case .failure(let error): print(error)
    }
}

Upvotes: 1

Related Questions