How to get string response from Retrofit2?

JavaAndroidHttpRetrofit2

Java Problem Overview


I am doing android, looking for a way to do a super basic http GET/POST request. I keep getting an error:

java.lang.IllegalArgumentException: Unable to create converter for class java.lang.String

Webservice:

public interface WebService {
    @GET("/projects")
    Call<String> jquery();
}

then in my java:

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://jquery.org")
       // .addConverterFactory(GsonConverterFactory.create())
        .build();

    WebService service = retrofit.create(WebService.class);
    Call<String> signin = service.jquery();

    Toast.makeText(this, signin.toString(), Toast.LENGTH_LONG).show();

I'm literally just trying to query jquery.org/projects with a GET request and return the String that it responds with. What is wrong?

If I try to implement a custom Converter (I've found a few examples online) it complains that I didn't implement the abstract method convert(F), which none of the examples do.

Thanks.

Java Solutions


Solution 1 - Java

Add Retrofit2 and ScalarsConverterFactory to your Retrofit.Builder.

adapterBuilder = new Retrofit.Builder()
               .addConverterFactory(ScalarsConverterFactory.create())
               .addConverterFactory(GsonConverterFactory.create());

To use ScalarsCoverter add following dependency to your build graddle

implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' 
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2

For API Call use: 
    Call <String> *****

Android Code :

.enqueue(new Callback<String>() {
    @Override
    public void onResponse(Call<String> call, Response<String> response) {
        Log.i("Response", response.body().toString());
        //Toast.makeText()
        if (response.isSuccessful()){
            if (response.body() != null){
                Log.i("onSuccess", response.body().toString());
            }else{
                Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
            }
        }

Solution 2 - Java

I take a look at Retrofit library and noticed that it parses response according to the type class inside Call<T>. So you have two option: 1st: create a class according to the response from the server.

2nd: get the response and handle it yourself (Not recommended Retrofit already handles it. So why do you use Retrofit as it is tailored for this job). Anyway instead of Call<String> use Call<ResponseBody> and Call<ResponseBody> signin = service.jquery(); after this put the following

call.enqueue(new Callback<ResponseBody>() {
  @Override
  public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
    // handle success
   String result = response.body().string();

  }

  @Override
  public void onFailure(Throwable t) {
    // handle failure
  }
});

Solution 3 - Java

To get the response as a String, you have to write a converter and pass it when initializing Retrofit.

Here are the steps.

Initializing retrofit.

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_URL_BASE)
                .addConverterFactory(new ToStringConverterFactory())
                .build();
        return retrofit.create(serviceClass);

Converter class for converting Retrofit's ResponseBody to String

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;
    }
}

And after executing service.jquery();, signin will contain JSON response.

Solution 4 - Java

You can try the following:

build.gradle file:

dependencies {
    ...
    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    ...
}

WebAPIService:

@GET("/api/values")
Call<String> getValues();

Activity file:

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_URL_BASE)                    
                .build();

        WebAPIService service = retrofit.create(WebAPIService.class);

        Call<String> stringCall = service.getValues();
        stringCall.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.i(LOG_TAG, response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.e(LOG_TAG, t.getMessage());
            }
        });

I have tested with my Web serivce (ASP.Net WebAPI):

public class ValuesController : ApiController
{
        public string Get()
        {
            return "value1";
        }
}

Android Logcat out: 04-11 15:17:05.316 23097-23097/com.example.multipartretrofit I/AsyncRetrofit2: value1

Hope it helps!

Solution 5 - Java

    call.enqueue(new Callback<Object>() {
        @Override
        public void onResponse(@NonNull Call<Object> call, @NonNull Response<Object> response) {
            if (response.isSuccessful()) {
                Gson gson = new Gson();
                String successResponse = gson.toJson(response.body());
                Log.d(LOG_TAG, "successResponse: " + successResponse);
            } else {
                try {
                    if (null != response.errorBody()) {
                        String errorResponse = response.errorBody().string();
                        Log.d(LOG_TAG, "errorResponse: " + errorResponse);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(@NonNull Call<Object> call, @NonNull Throwable t) {
        }
    });

Solution 6 - Java

Just use log level BODY in intercepror:

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()....
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        clientBuilder.addNetworkInterceptor(httpLoggingInterceptor);

And you can see body in logcat like:

        D/OkHttp: {"blablabla":1,.... }
        D/OkHttp: <-- END HTTP (1756-byte body)

This solution for debug only, not for get String directly in code.

Solution 7 - Java

thought it might be late to answer just use response.body()?.string() and you'll have your response as a string.

Solution 8 - Java

I change the Response type, instead of adding ScalarsConverterFactory like this

interface YourApiService {
@GET("/endpoint")
    fun getResponse(): Call<ResponseBody>
}

And then you can get the string object by

val str = response.body().toString()

Solution 9 - Java

String body = new String(((TypedByteArray) response.getBody()).getBytes());

if you found

java.lang.ClassCastException: retrofit.client.UrlConnectionClient$TypedInputStream cannot be cast to retrofit.mime.TypedByteArray

then put this in your RestAdapter

.setLogLevel(RestAdapter.LogLevel.FULL)

for Example:

RestAdapter restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint(Root_url)
            .build();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatthew DarnellView Question on Stackoverflow
Solution 1 - JavaNeyomalView Answer on Stackoverflow
Solution 2 - JavaugurView Answer on Stackoverflow
Solution 3 - JavaFarazView Answer on Stackoverflow
Solution 4 - JavaBNKView Answer on Stackoverflow
Solution 5 - JavaAhamadullah SaikatView Answer on Stackoverflow
Solution 6 - JavaTapa SaveView Answer on Stackoverflow
Solution 7 - JavaJoseph DaudiView Answer on Stackoverflow
Solution 8 - JavaRitesh AdulkarView Answer on Stackoverflow
Solution 9 - JavaAndroid DevView Answer on Stackoverflow