evermeer / EVReflection

Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift
Other
965 stars 119 forks source link

Extending Observable #305

Closed AdieOlami closed 5 years ago

AdieOlami commented 5 years ago

So, I was using Mapper and SwiftyJson before but I Just had a switch over to EVReflection which is a brilliant Library but I have issues extending Observable as I did so as to pass some custom response and all. below is the Mapper code and the new EVReflection that I am trying with Moya

extension Observable {

    /// 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 map to object
    /// - returns: Observable<T>
    func jsonMapObject<T: Mappable>(type: T.Type) -> Observable<Result<T, ORMError>> {

        return self.map { rawResult in

            guard let result = rawResult as? Result<JSON, ORMError> else {
                return .failure(ORMError.ORMParseJSONError)
            }

            switch result {
            case let .success(json):

                guard json != JSON.null,
                    let dict = json.dictionaryObject else {
                        return .failure(ORMError.ORMParseJSONError)
                }

                guard let object = Mapper<T>().map(JSON: dict) else {
                    return .failure(ORMError.ORMCouldNotMakeObjectError)
                }

                return .success(object)

            case let .failure(error):
                return .failure(error)
            }

        }
    }

    /// JSON map to object array
    /// - returns: Observable<[T]>
    func jsonMapArray<T: Mappable>(type: T.Type) -> Observable<Result<[T], ORMError>> {

        return self.map { rawResult in

            guard let result = rawResult as? Result<JSON, ORMError> else {
                return .failure(ORMError.ORMParseJSONError)
            }

            switch result {
            case let .success(json):

                guard json != JSON.null,
                    let jsonArray = json.array else {
                        return .failure(ORMError.ORMParseJSONError)
                }

                let dictArray = jsonArray.map { $0.dictionaryObject! }

                return .success(Mapper<T>().mapArray(JSONArray: dictArray))

            case let .failure(error):
                return .failure(error)
            }

        }
    }

    /// Trying with EVReflectable
    /// - returns: Observable<[T]>
    func jsonMapArray1<T: NSObject>(to type: T.Type, forKeyPath: String? = nil) -> Observable<Result<T, ORMError>>  where T: EVReflectable {

        return self.map { rawResult in

            guard let result = rawResult as? Result<JSON, ORMError> else {
                return .failure(ORMError.ORMParseJSONError)
            }

            switch result {
            case let .success(json):

                guard json != JSON.null,
                    let jsonArray = json.array else {
                        return .failure(ORMError.ORMParseJSONError)
                }

                let dictArray = jsonArray.map { $0.dictionaryObject! }

                return .success(EVObject.)

            case let .failure(error):
                return .failure(error)
            }

        }
    }

}

Any assistance would be very appreciated. Thanks

evermeer commented 5 years ago

Are you using the EVReflection/MoyaRxSwift extension? You could then extend ObservalbeType Here is a sample of my:

import RxSwift
import Moya
import EVReflection

public extension ObservableType where E == Response {

    /// Maps data received from the signal into an error if the statusCode != 0. alwasys call after mapJSON
    public func genericNetworkError() -> Observable<E> {
        return self.catchError { error in
            let message = self.getErrorMessage(error as NSError)
            let error: NSError = NSError(
                domain: "Midlayer",
                code: (error as NSError).code,
                userInfo: [NSLocalizedDescriptionKey: message,
                           "showErrorCodeToUser": true,
                           NSLocalizedFailureReasonErrorKey: error.localizedDescription])
            throw error
        }
    }

    private func getErrorMessage(_ error: NSError) -> String {
        var errorMessage: String = error.localizedDescription
        switch error.code {
        case NSURLErrorNotConnectedToInternet, // Returned when a network resource was requested, but an internet connection is not established and cannot be established automatically, either through a lack of connectivity, or by the user's choice not to make a network connection automatically.
        NSURLErrorUnsupportedURL, // Returned when a properly formed URL cannot be handled by the framework.
        NSURLErrorInternationalRoamingOff, // Returned when a connection would require activating a data context while roaming, but international roaming is disabled.
        NSURLErrorCallIsActive, // Returned when a connection is attempted while a phone call is active on a network that does not support simultaneous phone and data communication (EDGE or GPRS).
        NSURLErrorDataNotAllowed, // Returned when the cellular network disallows a connection.
        NSURLErrorSecureConnectionFailed, // Returned when an attempt to establish a secure connection fails for reasons which cannot be expressed more specifically.
        NSURLErrorCannotLoadFromNetwork, // Returned when a specific request to load an item only from the cache cannot be satisfied.
        NSURLErrorNetworkConnectionLost:        // Returned when a client or server connection is severed in the middle of an in-progress load.
            // Internet connection problems
            errorMessage = NSLocalizedString("noInternet", comment: "")
        default:
            errorMessage = NSLocalizedString("generalFailure", comment: "")
        }
        return errorMessage
    }
}

public extension ObservableType where E == Any {

    /// Decrypt the body for a cryptosession request
    public func decryptBody() -> Observable<Any> {
        return flatMap { result -> Observable<Any> in
            let error: NSError = NSError(
                domain: "Midlayer",
                code: 9000,
                userInfo: [NSLocalizedDescriptionKey: "Midlayer incorrect result",
                           "showErrorCodeToUser": true,
                           NSLocalizedFailureReasonErrorKey: "result: \(result)"])

            guard var dictionary = result as? [AnyHashable : Any] else { throw error }
            guard let body: String = dictionary["body"] as? String else { throw error }
            guard let vector: String = dictionary["initializationVector"] as? String else { throw error }

            let decrypted = SecureHelper.decryptWithAES(body, key: Midlayer.sessionKey ?? "", iv: vector) ?? ""
            dictionary["body"] = decrypted
            Stuff.print("⚡️✅ decrypted result:\n\(decrypted)")

            return Observable.just(dictionary)
        }
    }
}
evermeer commented 5 years ago

Do you have any update on this? Otherwise I will close the issue.