Decoding indeterminate types using JSON Decoder I'm working with a REST service that responds with indeterminate types. In particular, it can respond with a String, a correct payload (T: Decodable) or an error payload (PayloadError).
In order to cope with this type of requirement I've ended up with the following solution:
do {
    let decoder = JSONDecoder()
    let either = try decoder.decode(Either&lt;T, PayloadError&gt;.self, from: data)
    switch either {
        case .left(let value):
            completion(.success(value))
        case .right(let payloadError):
            completion(.failure(.generic)))
    }
} catch {
    if let value = String(data: data, encoding: .utf8) as? T {
        completion(.success(value))
    } else {
        completion(.failure(.generic))
    }
}

where Either is defined as:
enum Either&lt;T, U&gt; {
    case left(T)
    case right(U)
}

extension Either: Decodable where T: Decodable, U: Decodable {
    init(from decoder: Decoder) throws {
        if let value = try? T(from: decoder) {
            self = .left(value)
        } else if let value = try? U(from: decoder) {
            self = .right(value)
        } else {
            let context = DecodingError.Context(
                codingPath: decoder.codingPath,
                debugDescription: &quot;Cannot decode \(T.self) or \(U.self)&quot;
            )
            throw DecodingError.dataCorrupted(context)
        }
    }
}

Do you think the code looks good or should I use a more elegant solution?
Update 01.11.2020
These are the possible use cases along side with concrete responses.
Use Case 1
The client calls API method /authenticate. The server can responds with an authentication token of type String or a payload error of type PayloadError (if the server responds with unauthorized, for example). The JSON used to decode PayloadError is something like:
{
    code: 1,
    message: &quot;Error message here&quot;
}

PayloadError is defined as:
struct PayloadError: Decodable {
    let code: Int
    let message: String
}

Use Case 2
The client calls any other method. For example, it can call /user that gives back the info for the current user (the auth token is passed along). A struct User: Decodable is decoded from the returned JSON. If there is an error, the server replies with a PayloadError.
Based on the above use cases, the server can respond with:

String
T: Decodable (like User)
PayloadError

What I don't like is the code in catch since its intent is not clear.
I've finally end up splitting the two use cases. This in order to make the code readable and more maintainable.
PayloadError is mapped to a ServiceError: Error in order to align the output.
Use case 1
guard let data = response.data else {
    completion(.failure(.invalidData))
    return
}

let jsonDecoder = JSONDecoder()
if let payloadError = try? jsonDecoder.decode(PayloadError.self, from: data) {
    completion(.failure(ServiceError.from(payloadError)))
} else if let token = String(data: data, encoding: .utf8) {
    completion(.success(token))
} else {
    completion(.failure(.decodingError))
}

Use case 2
guard let data = response.data else {
    completion(.failure(.invalidData))
    return
}
let decoder = JSONDecoder()
guard let either = try? decoder.decode(Either&lt;T, PayloadError&gt;.self, from: data) else {
    completion(.failure(.decodingError))
    return
}
switch either {
case .left(let value):
    completion(.success(value))
case .right(let payloadError):
    completion(.failure(ServiceError.from(payloadError)))
}