2 Вопрос: Обработка ответа JSON Наблюдаемый Свифт

вопрос создан в Thu, May 2, 2019 12:00 AM

У меня есть приложение, которое использует 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[""]. Любая помощь приветствуется

    
1
2 ответа                              2                         

Я предлагаю вам попробовать что-то вроде этого:

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<Result<ResultType, ORMError>>

    
0
2019-05-03 00: 47: 14Z
  1. Это приводит к ошибке In argument type 'User.Type', 'User' does not conform to expected type 'ResponseType'
    2019-05-03 08: 51: 40Z
  2. Я создал список, содержащий код с swiftyJson 2019-05-03 09: 25: 21Z
  3. Согласуйте пользователя с ResponseType или создайте новый тип, который соответствует ResponseType и имеет пользователя в качестве ResultType.
    2019-05-03 10: 32: 15Z

Я хотел бы сделать расширение более 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)
    
0
2019-05-03 09: 10: 55Z
  1. Я хочу устранить ошибку и передать значение успеха в расширении
    2019-05-03 09: 24: 08Z
  2. Я создал список, содержащий код с swiftyJson 2019-05-03 09: 25: 14Z
  3. вы уже используете RxSwift, который несет за вас ошибку. и для результата вы указываете его в типе метода type. если вы хотите выполнить пользовательскую проверку ошибок, вы можете сделать что-то похожее, что было упомянуто выше, с новым методом filterServerError для любого имени, которое вам понравится, и просто выбросить туда ошибку, и RxSwift перенесет ее для вас, чтобы ее получил подписчик.
    2019-05-05 09: 52: 19Z
источник размещен Вот