【问题标题】:handling json response Observable swift处理 json 响应 Observable swift
【发布时间】:2019-05-02 15:09:59
【问题描述】:

我有一个使用 SwiftyJSON 并且可以工作的应用程序。但是,我现在想扩展项目并重构代码,但我遇到了一些问题,因为我现在切换到 Codable,我需要能够从任何路径而不是硬编码路径映射 JSON。目前我的 jsonResponse 看起来像这样

/// handle the network response and map to JSON
    /// - returns: Observable<JSON>
    func handleResponseMapJSON() -> Observable<Result<JSON, ORMError>> {

        return self.map { representor in

            guard let response = representor as? Moya.Response else {
                return .failure(ORMError.ORMNoRepresentor)
            }

            guard ((200...299) ~= response.statusCode) else {
                return .failure(ORMError.ORMNotSuccessfulHTTP)
            }

            guard let json = JSON.init(rawValue: response.data),
                json != JSON.null,
                let code = json["code"].int else {
                    return .failure(ORMError.ORMParseJSONError)
            }

            guard code == BizStatus.BizSuccess.rawValue else {
                let message: String = {
                    let json = JSON.init(data: response.data)
                    guard let msg = json["status"].string else { return "" }
                    return msg
                }()
                log(message, .error)
                return .failure(ORMError.ORMBizError(resultCode: "\(code)", resultMsg: message))
            }

            return .success(json["result"])

        }
    }

如何消除硬编码json[""] 值的通道。任何帮助表示赞赏

【问题讨论】:

    标签: swift rx-swift swifty-json codable moya


    【解决方案1】:

    我建议你试试这样的:

    protocol ResponseType: Codable {
        associatedtype ResultType
        var status: String { get }
        var code: Int { get }
        var result: ResultType { get }
    }
    
    func handleResponseMap<T, U>(for type: U.Type) -> (Any) -> Result<T, ORMError> where U: ResponseType, T == U.ResultType {
        return { representor in
            guard let response = representor as? Moya.Response else {
                return .failure(.ORMNoRepresentor)
            }
            guard ((200...299) ~= response.statusCode) else {
                return .failure(.ORMNotSuccessfulHTTP)
            }
            return Result {
                try JSONDecoder().decode(U.self, from: response.data)
                }
                .mapError { _ in ORMError.ORMParseJSONError }
                .flatMap { (response) -> Result<T, ORMError> in
                    guard response.code == BizStatus.BizSuccess.rawValue else {
                        log(response.status, .error)
                        return Result.failure(ORMError.ORMBizError(resultCode: "\(response.code)", resultMsg: response.status))
                    }
                    return Result.success(response.result)
            }
        }
    }
    

    然后你可以直接映射到你的 Codable 类型:

    let result = self.map(handleResponseMap(for: MyResponse.self))
    

    在上面,结果将是Observable&lt;Result&lt;ResultType, ORMError&gt;&gt;

    【讨论】:

    • 这会引发错误In argument type 'User.Type', 'User' does not conform to expected type 'ResponseType'
    • 我创建了一个要点,其中包含 swiftyJson gist.github.com/AdieOlami/ae4fb3ff70abdb576fe4842afebbbf2d 的代码和我想要实现的 Codable
    • 使 User 符合 ResponseType 或创建一个符合 ResponseType 并具有 User 作为 ResultType 的新类型。
    【解决方案2】:

    我想对PrimitiveSequenceType 进行扩展,将其视为Single

    import Foundation
    import RxSwift
    import Moya
    
     public extension PrimitiveSequenceType where TraitType == SingleTrait, ElementType == Response {
        func map<T>(_ type: T.Type, using decoder: JSONDecoder? = nil) -> PrimitiveSequence<TraitType, T> where T: Decodable {
            return self.map { data -> T in
                let decoder = decoder ?? JSONDecoder()
                return try decoder.decode(type, from: data.data)
            }
        }
    }
    

    你可以像这样简单地使用它:

    return  PokeAPIEndPoints.shared.provider.rx
            .request(.specieDetails(id: specieId))
            .filterSuccessfulStatusCodes()
            .map(SpecieDetails.self)
    

    【讨论】:

    • 我想解决错误并在扩展中传递成功值
    • 我创建了一个要点,其中包含 swiftyJson gist.github.com/AdieOlami/ae4fb3ff70abdb576fe4842afebbbf2d 的代码和我想要实现的 Codable
    • 您已经在使用 RxSwift,它会为您带来错误。对于结果,您可以在 type 方法的类型中指定它。如果您想进行自定义错误检查,您可以使用新方法filterServerError 执行与上面提到的类似的操作,任何您喜欢的名称,然后简单地在那里抛出错误,RxSwift 将携带它让您接收到订阅者。
    猜你喜欢
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 2020-05-14
    相关资源
    最近更新 更多