Retrofit with multiple converters

Alok Verma
MindOrks
Published in
2 min readOct 14, 2018

Hello Guys!! I have integrated retrofit with rxjava2.0 in my project, everything was going smooth, I have created a retrofit instance and was using GSON converter for my JSON like this-

new Retrofit.Builder()
.baseUrl(baseUrl)
.client(createClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setLenient().excludeFieldsWithoutExposeAnnotation().create()))
.build();

So Now suddenly my backend developer decided that there will be API for notifications and you have to parse XML or( in your case some new format), I am taking an example of XML here, so how to achieve multiple types of converters in the retrofit instance.

Now, There will be two options for solving this problem.

1- We create two retrofit instance and pass two different converters in each instance, Believe me, this is not a GOOD solution.

2- We create a class that will provide runtime converters to our retrofit singleton instance.

Here we are going to describe how to achieve this second solution.

First, we have to add XML converter in build.gradle

implementation "com.squareup.retrofit2:converter-simplexml:$retrofitVersion"

Now, we will create two annotated interface one for XML and other for JSON.

@Target(METHOD)
@Retention(RUNTIME)
@interface Xml {
}
@Target(METHOD)
@Retention(RUNTIME)
@interface Json {
}

And pass these annotations to our converter factory. In Api service interface, I added XML annotation in a method.

@GET @Xml
Observable<Channel> getSpriteMetaData(@Url String url);

Now we will create a class XmlOrJsonConverterFactory that will extends Converters. Factory class.

class XmlOrJsonConverterFactory extends Converter.Factory {    @Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
for (Annotation annotation : annotations) {
if (annotation.annotationType() == Xml.class) {
return SimpleXmlConverterFactory.createNonStrict(
new Persister(new AnnotationStrategy())).responseBodyConverter(type, annotations, retrofit);
}
if (annotation.annotationType() == Json.class) {
return GsonConverterFactory.create(new GsonBuilder().setLenient().excludeFieldsWithoutExposeAnnotation().create()).responseBodyConverter(type, annotations, retrofit);
}
}
return GsonConverterFactory.create(new GsonBuilder().setLenient().excludeFieldsWithoutExposeAnnotation().create()).responseBodyConverter(type, annotations, retrofit);
}
}

As you can see in response bodyConverter method, we get annotation that we pass in our API interface, so here we can check what type of converters is required.

Now we can pass this class in our retrofit instance

new Retrofit.Builder()
.baseUrl(baseUrl)
.client(createClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(new XmlOrJsonConverterFactory())
.build();

This instance will convert our response body to XML/JSON according to our requirement.

Thanks,

Alok V.

--

--

Alok Verma
MindOrks

Sr. Software Engineer @OYO, Cinema fanatic, Technology enthusiast.