处理 json 响应 Observable swift
handling json response Observable swift
我有一个使用 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[""]
值的通道。感谢任何帮助
我建议你尝试这样的事情:
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>>
我想对 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 并且可以运行的应用程序。然而,我现在想扩展项目并重构代码,但我遇到了一些问题,因为我现在切换到 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[""]
值的通道。感谢任何帮助
我建议你尝试这样的事情:
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>>
我想对 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)