Stack Overflow Asked by Renjith on December 22, 2021
I’m working on an application that uses Retrofit for network operations. As it stands, everything works well with GsonConverterFactory
handling serialization. Here is how I setup Retrofit
Retrofit.Builder()
.baseUrl("<base url>")
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
Now I need to connect to a legacy service which returns content in text/plain; charset=utf-8
format. Here is the Retrofit interface
@GET("https://<domain>/<endpoint>?Type=Query")
suspend fun callStatus(@Query("userId") id: Int): Response<String>
This will return status of a call for a valid user. For instance, if the user is valid and there is a status, it returns "Active" as plain text. If there is no valid user, it returns an error code of #1005
I could add custom converter factory like this (found on the web)
final class StringConverterFactory implements Converter.Factory {
private StringConverterFactory() {}
public static StringConverterFactory create() {
return new StringConverterFactory();
}
@Override
public Converter<String> get(Type type) {
Class<?> cls = (Class<?>) type;
if (String.class.isAssignableFrom(cls)) {
return new StringConverter();
}
return null;
}
private static class StringConverter implements Converter<String> {
private static final MediaType PLAIN_TEXT = MediaType.parse("text/plain; charset=UTF-8");
@Override
public String fromBody(ResponseBody body) throws IOException {
return new String(body.bytes());
}
@Override
public RequestBody toBody(String value) {
return RequestBody.create(PLAIN_TEXT, convertToBytes(value));
}
private static byte[] convertToBytes(String string) {
try {
return string.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
}
But I didn’t see it make any difference. Also, it could well disguise JSON as normal text and break all existing service. Is there a better way to handle this scenario? I thought of having separate retrofit instance for plain text, bit dirty though. Do you have any other suggestions/solutions?
Edited
Response header contains the content type as
Content-Type: text/plain; charset=utf-8
Actual response for valid user
Active
Actual response for invalid user
#1005
Two things to check first that function should not be suspended & your response should be in the Callback
No need to add extra implementation of scalars.
@GET
fun getJson(
@Url baseUrl: String = slab_pro
): Call<DataClass>
Answered by Adam Noor on December 22, 2021
The following is the way that how I get response as plain text (using Java not Kotlin).
Step One
in your gradle (Module);
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
Step Two
Create an interface
public interface MyInterface {
@GET("something.php")
Call<String> getData(@Query("id") String id,
@Query("name") String name);
}
Step Three
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.com")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
MyInterface myInterface = retrofit.create(MyInterface.class);
Call<String> call = myInterface.getData("id","myname");
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
String plain_text_response = response.body();
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
Answered by ZBorkala on December 22, 2021
The order in which you register the converter factories matters. ScalarsConverterFactory
must come first.
it should be possible by adding ScalarsConverterFactory
when building the Retrofit object.
This can be done alongside with other json converters, e.g.
Retrofit.Builder()
.baseUrl("<base url>")
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
After that, you should be able to receive plaintext responses.
You probably need to add this to your dependencies as well:
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
Answered by Adrian K on December 22, 2021
You don't need to use a your custom implementation of Converter.Factory
you could just use
// your coroutine context
val response = callStatus(userId)
if(response.isSuccessful){
val plainTextContent = response.body()
// handle plainText
} else {
//TODO: Handle error
}
//...
Answered by Arpan Sarkar on December 22, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP