使用 Codable 和 Combine 时转换 Alamofire 响应

Transforming Alamofire response when using Codable and Combine

我想使用 Alamofire 查询我的后端,使用 Alamofire 的内置 Codable 解析对响应进行编码,然后发布生成的 Struct 的提取物以供我的 API [=32] 的调用者使用=].假设我有一些来自后端的 JSON 数据(经过简化,但显示了结构):

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

和关联的 Codable 结构

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

struct Result: Codable {
    let foo: String
}

我可以通过以下方式获取、解析、发布和订阅一切正常:

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 */ }

我想做的是仅发布 [Result] 数组。正确的做法是什么?我是否应该使用 .responseDecodable() 并创建一个新的发布者(不知何故 - .map()?)returns 和 [Result].publisher

虽然我认为我理解基于 reactive/stream 的原则,但我的 Combine-fu 仍然很薄弱,而且我对从一个出版商到另一个出版商的转变没有明确的把握(我猜?)

提前致谢!

除了像 map 一样使用 Combine API 之外,Alamofire 在 DataResponsePublisher 本身上提供了两个发布者。

.result()DataResponse 中提取 Result 并创建一个 AnyPublisher<Result<Value, AFError>, Never>.

.value()DataResponse 中提取 Value 并创建一个失败的发布者 AnyPublisher<Value, AFError>.

因此,根据您想要的错误处理类型,这可能很简单:

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