Home > Back-end >  Transforming Alamofire response when using Codable and Combine
Transforming Alamofire response when using Codable and Combine

Time:05-27

I want to use Alamofire to query my backend, encode the response using Alamofire's built-in Codable parsing and then publish an extract from the resulting Struct to be consumed by the caller of my API class. Say I have some JSON data from my backend (simplified, but shows the structure):

{
    "total": 123,
    "results": [
        {"foo" : "bar"},
        {"foo" : "baz"}
    ]
}

and the associated Codable Structs

struct MyServerData: Codable {
    let total: Int
    let results: [Result]
}

struct Result: Codable {
    let foo: String
}

I can get, parse, publish, and subscribe all fine with the following:

func myAPI() -> DataResponsePublisher<MyServerData> {
    return AF.request("https://backend/path")
        .validate()
        .publishDecodable(type: MyServerData.self)
}

myAPI()
    .sink { response in /* Do stuff, e.g. update @State */ }

What I'd like to do is to publish just the [Result] array. What's the correct approach to this? Should I use .responseDecodable() and create a new publisher (somehow - .map()?) that returns a [Result].publisher?

While I think I understand the reactive/stream based principles my Combine-fu is still weak and I don't have a clear handle on the transformation of one publisher into another (I'm guessing?)

Thanks in advance!

CodePudding user response:

In addition to using Combine API like map, Alamofire offers two publishers on DataResponsePublisher itself.

.result() extracts the Result from the DataResponse and creates an AnyPublisher<Result<Value, AFError>, Never>.

.value() extracts the Value from the DataResponse and creates a failable publisher, AnyPublisher<Value, AFError>.

So depending on what kind of error handling you want, this could be as simple as:

...
  .publishDecodable(...)
  .value()
  .map(\.results)
  • Related