如何在 Swift 中使用 Combine 读取 JSON 错误对象的属性值?
Posted
技术标签:
【中文标题】如何在 Swift 中使用 Combine 读取 JSON 错误对象的属性值?【英文标题】:How do I read the property values of a JSON error object using Combine in Swift? 【发布时间】:2020-05-28 18:25:13 【问题描述】:我所有的 API 端点都返回一个在 Postman 中看起来像这样的响应:
"statusCode": 401,
"error": "Unauthorized",
"message": "Missing authentication"
我想做的是发出请求,并在 Swift 中访问这些属性。在某些情况下,我会在应用程序的前面使用错误消息属性的值。这将由返回的 statusCode 确定。
我现在拥有的是这样的:
private var cancellable: AnyCancellable?
let url = URL(string: "http://abc336699.com/create")
self.cancellable = URLSession.shared.dataTaskPublisher(for: url!)
.map $0.data
在此之前,我尝试过 tryMap,但它返回的错误类型并没有给我想要的灵活性。然后我继续尝试 Almofire,但对于我想做的事情来说,这似乎是一种过度杀戮。
我想检查我收到的响应中返回的内容,但我收到以下错误:
Cannot assign value of type 'Publishers.Map<URLSession.DataTaskPublisher, Data>' to type 'AnyCancellable'
我想要简单地访问我的响应错误,以便我可以使用 combine 将 API 集成到整个应用程序中。
【问题讨论】:
AnyCancellable
是一种通常由订阅者向发布者实现的协议,例如在.sink
或.assign
中使用的协议。 .map
是另一个发布者(不是订阅者)。如果需要处理错误,可以使用.catch
您为什么不根据您的 JSON 响应创建可解码模型并使用 Combine 中的解码运算符对其进行解码?
@user832 如果在 200 statusCode 响应后有数据要解码,那很好,但我也需要捕获错误。
@LondonGuy,这应该可以帮助你:developer.apple.com/documentation/foundation/urlsession/…
@LondonGuy 请记住,非 200 状态计数是网络成功。如果请求从未得到服务器的响应,数据任务发布者只会出错。如果服务器返回非 200 状态代码,您可以将其提取到 map
【参考方案1】:
我不确定您将从哪里获取数据,因为在 JSON 响应中没有数据密钥。在写下面的代码之前,我的理解是你想从提到的 JSON 响应中检查 error
和 statusCode
,然后继续你的业务逻辑。下面的代码是为了让您大致了解我们如何做到这一点。
enum CustomError: Error
case custom(_ error: String)
case unknownStatusCode
case errorOccurred
let url = URL(string: "http://abc336699.com/create")
func load() -> AnyPublisher<Data,CustomError>
URLSession.shared.dataTaskPublisher(for: url!)
.map(\.data)
.tryMap (data) -> Data in
let genericModel = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: AnyObject]
if let statusCode = genericModel?["statusCode"] as? String
switch statusCode
case "200":
guard let data = genericModel?["message"] as? Data else
throw CustomError.custom("Parsing error")
return data
default:
if let error = genericModel?["error"] as? String
throw CustomError.custom(error)
else
throw CustomError.unknownError
throw CustomError.errorOccurred
.decode(type: YourCustomDecodableModel.self, decoder: JSONDecoder())
.mapError( $0 as? CustomError ?? CustomError.errorOccurred )
.eraseToAnyPublisher()
【讨论】:
它的工作原理是,如果状态码不是200,我的问题中的对象会显示,如果状态码是200,会显示相同的对象,但状态码会是200,错误将是“成功”,消息将是数据,例如名字或其他东西的列表。 @LondonGuy 我根据您的评论更新了加载方法 这让我找到了答案:heckj.github.io/swiftui-notes/#reasoning-about-pipelines以上是关于如何在 Swift 中使用 Combine 读取 JSON 错误对象的属性值?的主要内容,如果未能解决你的问题,请参考以下文章
Swift Combine:如何从发布者列表中创建单个发布者?
如何通过另一个可观察对象观察已发布的属性 - Swift Combine
相当于在 Swift Combine 中使用 @Published 计算的属性?