Skip to content

Instantly share code, notes, and snippets.

@swankjesse
Created May 31, 2019 03:58
Show Gist options
  • Save swankjesse/bfae62dba85c87fa775b4a1f39e4867e to your computer and use it in GitHub Desktop.
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
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