Search code examples
javaandroidjsonretrofit

How to Read response if "response.isSuccessful()" is true in Retrofit


JSON Response from API:

{
    "type": "loginResponseMessage",
    "statusCode": 200,
    "statusMessage": "Login Successful",
    "resource_id": 3
}

I want to read JSON response. When 'if(response.isSuccessful())' is executing I am getting null pointer exception. In case of execution of 'else' block I am getting correct response. Following is the code:

@Override
            public void onResponse(Call<Login> call, Response<Login> response) {
            if (response.isSuccessful()) {
                LoginResponseMessage loginResponseMessage;

                loginResponseMessage = new APIResponse().getResponse2(retrofit,response);

                String toastMessage = "StatusMessage: "+loginResponseMessage.getStatusMessage()
                        +"Status Code: "+loginResponseMessage.getStatusCode()
                        +"ResourceId: "+loginResponseMessage.getResource_id();
                Toast.makeText(LoginActivity.this,toastMessage, Toast.LENGTH_SHORT).show();
            } else {

                switch(response.code()){
                    case 401:
                        LoginResponseMessage loginResponseMessage;

                        loginResponseMessage = new APIResponse().getResponse2(retrofit,response);

                        String toastMessage = "StatusMessage: "+loginResponseMessage.getStatusMessage()
                                +"Status Code: "+loginResponseMessage.getStatusCode()
                                +"ResourceId: "+loginResponseMessage.getResource_id();
                        Toast.makeText(LoginActivity.this,toastMessage, Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        }

Class APIResponse:

public class APIResponse {
    private String statusMessage;

    public LoginResponseMessage getResponse2(Retrofit retrofit, Response response){         //This will only be called in LoginActivity
        LoginResponseMessage responseMessage = new LoginResponseMessage();

        Converter<ResponseBody, LoginResponseMessage> converter
                = retrofit.responseBodyConverter(LoginResponseMessage.class, new Annotation[0]);
        try {
            responseMessage = converter.convert(response.errorBody());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseMessage;
    }
}

Same logic is applied in 'if' & 'else' block. But getting null pointer exception in 'if (response.isSuccessful())' block

java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Reader okhttp3.ResponseBody.charStream()' on a null object reference
                                                                      at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:35)
                                                                      at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
                                                                      at pk.qareeb.qareeb.LoginActivity$5.onResponse(LoginActivity.java:206)
                                                                      at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
                                                                      at android.os.Handler.handleCallback(Handler.java:761)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:98)
                                                                      at android.os.Looper.loop(Looper.java:156)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:6523)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)
t

2nd Approach: I have also tried following code.

@Override
     public void onResponse(Call<Login> call, Response<Login> response) {
         Toast.makeText(LoginActivity.this,response.body().toString(),Toast.LENGTH_LONG).show();
}

By adding 2nd approach code, instead of toasting JSON response, it is toasting "com.qareeb.qareeb.modal.Login@119c611". Why ?


Solution

  • In your Second approach you are printing the instance of Login class. it's not an error or issue. If you want to see the response then override the toString() method inside your Login class or you can also check the properties inside your Login class one by one.

    Edit- As I understand you are using Login(for request) class here instead of a Response(to get the response) class. So use your Login class to send a request and LoginResponse class to get the login response.

    Make a separate class name LoginResponse and use it instead of Login in your network call.

    LoginResponse.java

    public class LoginResponse
    {
       private String statusCode;
    
       private String resource_id;
    
       private String type;
    
        private String statusMessage;
        // getter and setters.
        .
        .
        @Override
        public String toString()
        {
            return "LoginResponse [statusCode = "+statusCode+", resource_id = "+resource_id+", type = "+type+", statusMessage = "+statusMessage+"]";
        }
    }
    

    Now do it like-

    @Override
     public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
         Toast.makeText(context, LoginResponse.toString(), Toast.LENGTH_LONG).show();
     }
    

    Or

    @Override
     public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
         LoginResponse loginResponse = response.body();
         Toast.makeText(context, loginResponse.getStatusMessage (), Toast.LENGTH_LONG).show();
         Toast.makeText(context, loginResponse.getType (), Toast.LENGTH_LONG).show();
     }