Search code examples
iosrx-swiftrx-cocoamoya

Is it possible to map to a "fallback" Decodable using RxSwift and Moya?


I am using RxMoya for the network layer of my app and I'm having a case where the server can either send the expected response (let's say a User), or an error object, both with status code 200. For example:

{
  "name": "john doe",
  "username": "john_doe"
}

could be the expected response and

{
  "error": {
    "code": 100,
    "message": "something went wrong™"
  }
}

could be the error.

The relevant part of the network adapter could look like this:

    return provider
        .rx
        .request(MultiTarget.target(target))
        .map(User.self)
        // if above fails, try:
        // .map(UserError.self)
        .asObservable()

Is there a way to firstly try and .map(User.self) and if that fails, try to .map(UserError.self) in the same chain of operations? In other words, could I provide an alternative mapping model using Rx?


Solution

  • You could use flatMap to do that. Something like this:

        return provider
        .rx
        .request(MultiTarget.target(target))
        .flatMap { response -> Single<User> in
            if let responseType = try? response.map(User.self) {
                return Single.just(responseType)
            } else if let errorType = try? response.map(UserError.self) {
                return Single.error(errorType.error)
            } else {
                fatalError("⛔️ We don't know how to parse that!")
            }
         }
    

    BTW, status code 200 to return an error is not correct.