6

I passed an update user request on postman and got a successful response (see image), Now when I try to do the same in my app, using Retrofit 2, I get error as com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $. Interestingly I have come across this error earlier, and I know that this usually happens if my Model is not according to the response. But this time I think I have checked all the boxes but sill I'm getting the error. If anybody could figure out where I'am going wrong...

My Response in Postman:

enter image description here

My Pojo:

package com.example.evidya.Retrofit.Model.EditModel;

import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class EditResponse {
    @SerializedName("result")
    @Expose
    private String result;

    @SerializedName("response_code")
    @Expose
    private Integer responseCode;

    @SerializedName("msg")
    @Expose
    private String msg;

    @SerializedName("data")
    @Expose
    private List<Object> data = null;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public Integer getResponseCode() {
        return responseCode;
    }

    public void setResponseCode(Integer responseCode) {
        this.responseCode = responseCode;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public List<Object> getData() {
        return data;
    }

    public void setData(List<Object> data) {
        this.data = data;
    }

}

My Retrofit Client:

package com.example.evidya.Retrofit;

import com.example.evidya.Common.Common;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClient {
    public static Retrofit retrofit = null;
    public static Retrofit getRetrofit(){
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder httpClient = new OkHttpClient.Builder()        //adding custom interceptor
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS);
        httpClient.addInterceptor(loggingInterceptor); //add logging interceptor as the last interceptor,
                                                       // because this shall also show other interceptors
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        if(retrofit == null){
            retrofit= new Retrofit.Builder()
                    .baseUrl(Common.baseUrl)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .client(httpClient.build())
                    .build();
        }
        return retrofit;
    }
}

Retrofit interface:

@FormUrlEncoded
@PUT("user/update_user")
Call<EditResponse> updateUser(
    @HeaderMap Map<String, String> headers,
    @Field("user_id") String id,
    @Field("email") String email,
    @Field("name") String name,
    @Field("phone") String phone,
    @Field("access_token") String accessToken
);

My OkHttp Response: enter image description here

My Code:

private void saveRequest() {
    Log.d(TAG, "saveRequest: "+loginResponseData.getId());
    progressDialog.setMessage("Updating...");
    progressDialog.show();
    String name, email, mobile;

    name = mName.getText().toString();
    email = mEmail.getText().toString();
    mobile = mPhoneNumber.getText().toString();

    Call<EditResponse> editResponseCall = evidya.updateUser(Common.getHeaders(), loginResponseData.getId(), email, name, mobile, loginResponseData.getAccessToken());
    editResponseCall.enqueue(new Callback<EditResponse>() {
        private int retryCount = 0;

        @Override
        public void onResponse(Call<EditResponse> call, Response<EditResponse> response) {
            progressDialog.dismiss();
            if(!response.isSuccessful()){
                Toast.makeText(Edit_AccountActivity.this, ""+response.message(), Toast.LENGTH_SHORT).show();
                return;
            }

            EditResponse loginResponse = null;
            try {
                loginResponse = response.body();
            } catch (Exception e) {
                Log.d(TAG, "onResponse: error parsing"+e.toString());
            }

            if(loginResponse != null){
                if(loginResponse.getResult().toLowerCase().equals("success")){
                    Toast.makeText(Edit_AccountActivity.this, "Your details successfully updated", Toast.LENGTH_SHORT).show();
                } else{
                    Toast.makeText(Edit_AccountActivity.this, ""+loginResponse.getMsg(), Toast.LENGTH_SHORT).show();
                }

            } else{
                Toast.makeText(Edit_AccountActivity.this, "Invalid Response from server", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<EditResponse> call, Throwable t) {
            Log.d(TAG, "onFailure: "+t.toString());
            Toast.makeText(Edit_AccountActivity.this, ""+t.getMessage(), Toast.LENGTH_SHORT).show();
            progressDialog.dismiss();
        }


    });
}
Pradip Tilala
  • 1,715
  • 16
  • 24
Shikhar
  • 644
  • 1
  • 10
  • 20
  • "com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $." this error usually comes when the response contains a **string** rather than **JSON data**. check whether you are getting correct response and also passing correct data – Viswas Kg Apr 12 '19 at 04:50

2 Answers2

4

This usually happens when you're receiving something other than the expected response from the server.
To understand what's wrong try imitate your request in Postman and see what you receive from server.
Moreover you can turn on OkHttp's Logging Interceptor to see exactly what the server returns in your Logcat.

2hamed
  • 8,719
  • 13
  • 69
  • 112
  • I have already done that, infact you can check my OkHttp response in the image that I have posted – Shikhar Apr 12 '19 at 04:36
  • Well it's obvious you're not receiving a pure JSON response. I can see a `SQL Query` in your response body prior to your json. – 2hamed Apr 12 '19 at 04:39
  • 1
    You got it right man, Now i have learnt to also check the html response along with the json response in postman. This thing was really getting into my head. Thanks a lot brother. – Shikhar Apr 12 '19 at 04:51
2

add @Headers({"Accept: application/json"}) in Retrofit interface work for me

 @Headers({"Accept: application/json"})
 @POST("user/classes")
 Call<playlist> addToPlaylist(@Body PlaylistParm parm);
emad pirayesh
  • 654
  • 7
  • 12