// // ObjectMapper+Combine.swift // // Created by Thibaut Schmitt on 04/12/2020. // import Combine import Foundation import ObjectMapper /* Usage: requestPublisher .performRequest(session: urlSession) .keepOnlyDataFromDataTaskResponseTuple() .decodeArray(type: MyObject.self, context: mappingContext) or .decodeObject(type: MyObject.self, context: mappingContext) */ // MARK: - Publisher public extension Publisher where Output == Data, Failure == Error { func decodeObject(type: T.Type, context: MapContext? = nil) -> AnyPublisher where T: BaseMappable { self.tryMap { let decoder = ObjectMapperDecoder(context: context) return try decoder.decodeObject(type, from: $0) } .eraseToAnyPublisher() } func decodeArray(type: T.Type, context: MapContext? = nil) -> AnyPublisher<[T], Error> where T: BaseMappable { self.tryMap { data -> [T] in let decoder = ObjectMapperDecoder(context: context) return try decoder.decodeArray(type, from: data) } .eraseToAnyPublisher() } } // MARK: - Decoder public struct ObjectMapperDecoder { public enum ObjectMapperDecoderError: Error { case cantConvertDataToUTF8String case cannotParsedData } public typealias Input = Data let context: MapContext? public init(context: MapContext?) { self.context = context } public func decodeArray(_ type: T.Type, from: Input) throws -> [T] where T: BaseMappable { guard let decoded = String(data: from, encoding: String.Encoding.utf8) else { throw ObjectMapperDecoderError.cantConvertDataToUTF8String } let mapper = Mapper(context: context) if let obj = mapper.mapArray(JSONString: decoded) { return obj } throw ObjectMapperDecoderError.cannotParsedData } public func decodeObject(_ type: T.Type, from: Input) throws -> T where T: BaseMappable { guard let decoded = String(data: from, encoding: String.Encoding.utf8) else { throw ObjectMapperDecoderError.cantConvertDataToUTF8String } let mapper = Mapper(context: context) if let obj = mapper.map(JSONString: decoded) { return obj } throw ObjectMapperDecoderError.cannotParsedData } }