2

I used retrofit to get a response from the API, but I got different types of response from the same API, like these

  1. JsonObject
  2. String type
  3. Boolean Type

Based on the situation, it gives different types of responses from the same API.
I tried to use this code:

   serverUtilities.getBaseClassService(getApplicationContext(), "").forgotPasswordSecurityAnswerCheck(in, new Callback<JsonObject>() {
        @Override
        public void success(JsonObject s, retrofit.client.Response response) {
            Log.d("forgot_password_respons", "--->" + "" + s.toString());

           /* to retrieve the string or integer values*/

            if (s.toString().equals("5")) {
                utilities.ShowAlert("selected wrong question", "Forgot Password SecQues");

            }
            if (s.toString().equals("1")) {
                // some alert here

            }

           /* to retrieve the boolean  values*/

            if (s.toString().equals("false")) {
                utilities.ShowAlert(getResources().getString(R.string.otp_fail), "Forgot Password SecQues");

            }

            if (s.toString().equals("1")) {
                utilities.ShowAlert("Email already registered", "Social Registration");

            }
       /*to retrieve the Json object*/

         else
            if (s.toString().charAt(0) == '{') {
                Log.d("my_first_char", "" + s.toString().charAt(0));

                try {
                    if (s.toString().contains("memberId")) {
                        String MemberId = s.get("memberId").getAsString();
                        String optId = s.get("otpId").getAsString();
                        Log.d("Forgot_pass_ques_act", "" + MemberId + "--->" + optId);

                        Singleton.setSuccessId(MemberId);
                        Singleton.setOptId(optId);
                        Intent intent = new Intent(ForgotPasswordQuestionActivity.this, PasswordActivity.class);
                        startActivity(intent);
                        Toast.makeText(ForgotPasswordQuestionActivity.this, "congrats!! second step Success ", Toast.LENGTH_SHORT).show();

                    } else if (s.toString().contains("mId")) {

                    }
                } catch (Exception e) {
                    utilities.ShowAlert(e.getMessage(), "forgot passwordQues(catch)");

                    Log.d("forgot_password_error", "" + e.getMessage());
                }


                // Singleton.setSuccessId(s);
            }
        }

        @Override
        public void failure(RetrofitError error) {
            utilities.ShowAlert(error.getMessage(), "forgot passwordQues(server)");

            Log.d("forgot_passwo_secAnser", "--->" + error.getMessage());

        }
    });

Here I kept that return type as "jsonObject" in the call back and converted in to a string and checked whether it was a JsonObject or boolean or String and perform the actions related to that.
But I got this exception while handling the responses:

Response:

     com.google.gson.JsonSyntaxException:Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive

Can anyone suggest me how to handle these responses in single type of Callback in retrofit?

If I used a String type as a callback like this:

server_utilities.getBaseClassService(getApplicationContext(), "").forgotPasswordResponse(in, new Callback<String>() {
        @Override
        public void success(String s, retrofit.client.Response response) {
            Log.d("forgot password resp", "--->" + "" + s.toString());

        }

        @Override
        public void failure(RetrofitError error) {


            Log.d("forgot_password_error", "--->" + error.getMessage());

        }
    });
}

I am getting this error:

 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $ 
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
uma
  • 259
  • 3
  • 22

2 Answers2

0

The server can't give you a boolean object, and Retrofit is automatically converting a String to a JSONObject for you since that's the type you told it

To stop that, just request a string, and parse it later

new Callback<String>() 

or perhaps

new Callback<JsonPrimitive>() 

You can also get response.raw attribute (which is in Retrofit 2.x)

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • if i will use Callback when i want JsonObject: it gives the follwing error com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $ ....if i will use Callback when i want "String" it will give ---> com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $ ---->i dont know how to handle boolean response – uma Jul 26 '17 at 15:07
  • You should only use Retrofit **with the Gson converter** if you *always* get a JSON response – OneCricketeer Jul 26 '17 at 19:26
  • Related: https://stackoverflow.com/questions/32617770/how-to-get-response-as-string-using-retrofit-without-using-gson-or-any-other-lib – OneCricketeer Jul 26 '17 at 19:29
0

declare tag type as Object

@SerializedName("response") @Expose public Object response; and after getting response check the type and convert to accordingly

if (response.body().response!=null &&  response.body().response instanceof Collection<?>) {
            //if you find response type is collection then convert to json then json to real collection object
            String responseStr = new Gson().toJson(data.diagnosis.provisionalDiagnosis);
            Type type=new TypeToken<List<Response>>(){}.getType();
            List<Response> responseList=new Gson().fromJson(responseStr,type);
            if(responseList.size() > 0){
                patientInfoBinding.phoneTv.setText(responseList.get(0).phnNo);
            }
        }else if (response.body() instanceof String){
            String res=response.body();
        }else {}

like above you can check instanceof String/instanceof Boolean

Mohd Qasim
  • 896
  • 9
  • 20