Skip to content

Instantly share code, notes, and snippets.

@cbeyls
Created January 5, 2025 16:04
Show Gist options
  • Save cbeyls/dac2023d390696f87ff8265c025fb2a5 to your computer and use it in GitHub Desktop.
Save cbeyls/dac2023d390696f87ff8265c025fb2a5 to your computer and use it in GitHub Desktop.
A Retrofit Converter.Factory using the Json format from the Kotlin Serialization library, optimized to stream response bodies
package be.digitalia.retrofit2
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.serializer
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Retrofit
import java.lang.reflect.Type
/**
* A Retrofit Converter.Factory using the Json format from the Kotlin Serialization library,
* optimized to stream response bodies.
*/
@OptIn(ExperimentalSerializationApi::class)
internal class JsonStreamingFactory(
private val serializer: Json
) : Converter.Factory() {
override fun responseBodyConverter(
type: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): Converter<ResponseBody, *> {
val loader: DeserializationStrategy<Any> = serializer.serializersModule.serializer(type)
return Converter { responseBody ->
responseBody.use {
serializer.decodeFromStream(loader, responseBody.byteStream())
}
}
}
override fun requestBodyConverter(
type: Type,
parameterAnnotations: Array<out Annotation>,
methodAnnotations: Array<out Annotation>,
retrofit: Retrofit
): Converter<*, RequestBody> {
val saver: SerializationStrategy<Any> = serializer.serializersModule.serializer(type)
return Converter<Any, RequestBody> { value ->
serializer.encodeToString(saver, value).toRequestBody(MEDIA_TYPE)
}
}
companion object {
private val MEDIA_TYPE = "application/json; charset=UTF-8".toMediaType()
}
}
@JvmName("create")
fun Json.asStreamingConverterFactory(): Converter.Factory {
return JsonStreamingFactory(this)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment