I have the following model:
struct Response: Decodable {
let message: String
}
struct ErrorResponse: Decodable {
let errorMessage: String
}
enum APIError: Error {
case network(code: Int, description: String)
case decoding(description: String)
case api(description: String)
}
I'm trying to fetch an url and parse the JSON response using this flow:
func fetch(url: URL) -> AnyPublisher<Response, APIError> {
URLSession.shared.dataTaskPublisher(for: URLRequest(url: url))
// #1 URLRequest fails, throw APIError.network
.mapError { .network(code: $0.code.rawValue, description: $0.localizedDescription) }
// #2 try to decode data as a `Response`
.tryMap { JSONDecoder().decode(Response.self, from: $0.data) }
// #3 if decoding fails, decode as an `ErrorResponse`
// and throw `APIError.api(description: errorResponse.errorMessage)`
// #4 if both fail, throw APIError.decoding
// #5 return
.eraseToAnyPublisher()
}
I have a problem with #3: how can I decode the original data after the tryMap part?
It seems like the only value I can access there is the error coming from tryMap but I need the original data to decode an ErrorRepsonse.
Note: unfortunately the error response comes with the 200 status and the only way to differentiate them is to decode them.