Skip to content

Instantly share code, notes, and snippets.

@titiphoque
Created April 29, 2021 13:44
Show Gist options
  • Save titiphoque/7c6f61d4f0629451b3a2d217b2ce4f94 to your computer and use it in GitHub Desktop.
Save titiphoque/7c6f61d4f0629451b3a2d217b2ce4f94 to your computer and use it in GitHub Desktop.
Combine extension allowing parsing data with ObjectMapper framework
//
// 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<T>(type: T.Type, context: MapContext? = nil) -> AnyPublisher<T, Error> where T: BaseMappable {
self.tryMap {
let decoder = ObjectMapperDecoder(context: context)
return try decoder.decodeObject(type, from: $0)
}
.eraseToAnyPublisher()
}
func decodeArray<T>(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<T>(_ 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<T>(context: context)
if let obj = mapper.mapArray(JSONString: decoded) {
return obj
}
throw ObjectMapperDecoderError.cannotParsedData
}
public func decodeObject<T>(_ 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<T>(context: context)
if let obj = mapper.map(JSONString: decoded) {
return obj
}
throw ObjectMapperDecoderError.cannotParsedData
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment