Created
May 31, 2019 03:58
-
-
Save swankjesse/bfae62dba85c87fa775b4a1f39e4867e to your computer and use it in GitHub Desktop.
Retrofit converter that gives you both the raw response bytes and the converted object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import okhttp3.ResponseBody | |
import okhttp3.mockwebserver.MockResponse | |
import okhttp3.mockwebserver.MockWebServer | |
import okio.ByteString | |
import okio.ByteString.Companion.encodeUtf8 | |
import org.assertj.core.api.Assertions.assertThat | |
import org.junit.Rule | |
import org.junit.Test | |
import retrofit2.Call | |
import retrofit2.Converter | |
import retrofit2.Retrofit | |
import retrofit2.http.GET | |
import java.io.IOException | |
import java.lang.reflect.ParameterizedType | |
import java.lang.reflect.Type | |
class BytesAndValueTest { | |
@JvmField @Rule val server = MockWebServer() | |
internal interface Api { | |
@GET("/") fun invoke(): Call<BytesAndValue<Long>> | |
} | |
@Test @Throws(IOException::class) | |
fun test() { | |
val retrofit = Retrofit.Builder() | |
.baseUrl(server.url("/")) | |
.addConverterFactory(HexConverter) | |
.addConverterFactory(BytesAndValueConverter) | |
.build() | |
val example = retrofit.create(Api::class.java) | |
server.enqueue(MockResponse().setBody("b0b15c00")) | |
val response = example.invoke().execute() | |
assertThat(response.body()!!.bytes).isEqualTo("b0b15c00".encodeUtf8()) | |
assertThat(response.body()!!.value).isEqualTo(2964413440L) | |
} | |
object BytesAndValueConverter : Converter.Factory() { | |
override fun responseBodyConverter( | |
type: Type, | |
annotations: Array<Annotation>, | |
retrofit: Retrofit | |
): Converter<ResponseBody, *>? { | |
if (getRawType(type) !== BytesAndValue::class.java) return null | |
val valueType = getParameterUpperBound(0, type as ParameterizedType) | |
val valueConverter = retrofit.responseBodyConverter<Any>(valueType, annotations) | |
return Converter<ResponseBody, BytesAndValue<Any?>> { responseBody -> | |
val bytes = responseBody.source().peek().readByteString() | |
val value = valueConverter.convert(responseBody) | |
BytesAndValue(bytes, value) | |
} | |
} | |
} | |
data class BytesAndValue<T>( | |
var bytes: ByteString, | |
var value: T | |
) | |
object HexConverter : Converter.Factory() { | |
override fun responseBodyConverter( | |
type: Type, | |
annotations: Array<Annotation>, | |
retrofit: Retrofit | |
): Converter<ResponseBody, *>? { | |
if (getRawType(type) !== Long::class.javaObjectType) return null | |
return Converter<ResponseBody, Long> { it.source().readHexadecimalUnsignedLong() } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment