Mobile Development 7 min read

Eliminate BaseResponse Wrapper in Retrofit Using a Custom Converter.Factory

This article presents a Kotlin‑based technique for removing the repetitive BaseResponse wrapper from Retrofit calls by introducing a custom Converter.Factory and annotation‑driven ConvexTransformer that automatically extracts the data payload.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Eliminate BaseResponse Wrapper in Retrofit Using a Custom Converter.Factory

When backend APIs return a uniform wrapper such as BaseResponse (containing fields like code , data , message ), developers often have to write repetitive code to unwrap the data field in every Retrofit service method.

This article proposes an elegant solution that removes the need for a BaseResponse type by creating a custom Converter.Factory (named ConvexConverterFactory ) which intercepts the method annotations, applies a user‑defined ConvexTransformer , and forwards the transformed InputStream to the regular Gson converter.

The key steps are:

Define a ConvexTransformer interface that converts the original response stream into a stream containing only the business data .

Create a @Transformer annotation that references a concrete ConvexTransformer class and apply it to Retrofit service methods.

Implement ConvexConverterFactory and ConvexConverter that detect the annotation, obtain the appropriate transformer, and delegate the final conversion to the next factory (e.g., GsonConverterFactory ).

Register ConvexConverterFactory as the first converter in the Retrofit.Builder .

Example code snippets:

public interface UserService {
    @GET("/users")
    @Transformer(TestConvexTransformer::class)
    suspend fun getAllUsers(): List
}
class ConvexConverterFactory : Converter.Factory() {
    override fun responseBodyConverter(
        type: Type,
        annotations: Array
,
        retrofit: Retrofit
    ): Converter
? {
        return annotations.filterIsInstance
()
            .firstOrNull()?.value?.let { transformerClazz ->
                retrofit.nextResponseBodyConverter
(this, type, annotations)
                    ?.let { converter -> ConvexConverter(transformerClazz, converter) }
            }
    }
}
interface ConvexTransformer {
    @Throws(IOException::class)
    fun transform(original: InputStream): InputStream
}

Finally, the article shows a complete usage scenario with the public WanAndroid API, demonstrating how to define a WanAndroidConvexTransformer , a service interface, and how to invoke the API inside a coroutine.

The approach centralises the unwrapping logic, supports multiple response formats, and leverages Retrofit’s extensibility via the annotations parameter of Converter.Factory .

AndroidKotlinnetworkingRetrofitConverterCustomAnnotation
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.