如何使用 Combine in Swift 读取 JSON 错误对象的 属性 值?

How do I read the property values of a JSON error object using Combine in Swift?

我的所有 API 端点 return 在 Postman 中看起来像这样的响应:

{
    "statusCode": 401,
    "error": "Unauthorized",
    "message": "Missing authentication"
}

我想做的是发出请求,并访问 Swift 中的这些属性。在某些情况下,我会在应用程序的前面使用错误消息 属性 的值。这将由 statusCode returned.

决定

我现在有的是:

    private var cancellable: AnyCancellable?
    let url = URL(string: "http://abc336699.com/create")
    self.cancellable = URLSession.shared.dataTaskPublisher(for: url!)
      .map { [=14=].data }

在此之前,我尝试了 tryMap,但它 returned 的错误类型并没有给我想要的灵活性。然后我继续尝试 Almofire,但它似乎对我想做的事来说太过分了。

我想检查 return 收到的响应中的内容,但出现以下错误:

Cannot assign value of type 'Publishers.Map<URLSession.DataTaskPublisher, Data>' to type 'AnyCancellable'

我想简单地访问我的响应错误,这样我就可以使用 combine 在整个应用程序中集成 API。

我不确定您将从哪里获取数据,因为在 JSON 响应中没有数据密钥。在编写下面的代码之前,我的理解是您想从提到的 JSON 响应中检查 errorstatusCode,然后继续您的业务逻辑。下面的代码是为了让您对我们如何做到这一点有一个模糊的了解。

    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({ [=10=] as? CustomError ?? CustomError.errorOccurred })
    .eraseToAnyPublisher()
}