Get String response body from retrofit2

Muhammad Umar picture Muhammad Umar · Feb 20, 2016 · Viewed 14k times · Source

I am using retrofit1 old style

@GET("/loginUser")
    public Call<Response> login(
            @Query("email") String email,
            @Query("password") String password,
            Callback<Response> callback);

Now i don't want to get "User" class however i want to get a String response.

Previously we were using "Response" However there is no Response in retrofit2,

How can i get string response or full body response from the server without using any json parsing?

Answer

Ankit Aggarwal picture Ankit Aggarwal · Feb 20, 2016

Create this class

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

public class ToStringConverterFactory extends Converter.Factory {
    private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (String.class.equals(type)) {
            return new Converter<ResponseBody, String>() {
                @Override
                public String convert(ResponseBody value) throws IOException {
                    return value.string();
                }
            };
        }
        return null;
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

        if (String.class.equals(type)) {
            return new Converter<String, RequestBody>() {
                @Override
                public RequestBody convert(String value) throws IOException {
                    return RequestBody.create(MEDIA_TYPE, value);
                }
            };
        }
        return null;
    }
}

use it with

Retrofit retrofit = new Retrofit.Builder()
                        .addConverterFactory(new ToStringConverterFactory())
                        .build();

EDIT: You have to define it as

@GET("/loginUser")
    public Call<String> login(
            @Query("email") String email,
            @Query("password") String password);

There is no callback supported in retrofit2 so you have to remove that. To make it asynchronous, you have to do

Call<String> call = service.login(username, password);
call.enqueue(new Callback<String>() {}

EDIT The above code was for retrofit2 beta 3. For retrofit:2.1.0, you have to create ToStringConverterFactory as -

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

public class ToStringConverterFactory extends Converter.Factory {
    private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (String.class.equals(type)) {
            return new Converter<ResponseBody, String>() {
                @Override
                public String convert(ResponseBody value) throws IOException {
                    return value.string();
                }
            };
        }
        return null;
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
                                                          Annotation[] methodAnnotations, Retrofit retrofit) {

        if (String.class.equals(type)) {
            return new Converter<String, RequestBody>() {
                @Override
                public RequestBody convert(String value) throws IOException {
                    return RequestBody.create(MEDIA_TYPE, value);
                }
            };
        }
        return null;
    }
}

GOOD TO KNOW: Incase you want to have multiple converters (e.g. a String converter as shown above and also a GSON converter):
Make sure you specify the special-purpose converters first (e.g. String converter) and general converters (like Gson) last!

Converters will be called by the order they have been added, if a converter consumed the response, the follwoing converters will not be called.