user8164155
user8164155

Reputation: 127

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT -ANDROID RETROFIT2

I have seen this question several times asked in stackoverflow.but those answers not fixed my issue and i'm new to retrofit.i'm using retrofit for my login interface.i'm sending username,password then response will be two tokens inside a array.when i trying to login,log cat showing java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT

Request

POST : form-urlencorded

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(AllConstants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();


  public void getUser(String username,String password){

        WebserviceAPI apiService =retrofit.create(WebserviceAPI.class);
        Call<UserResponse> call = apiService.getUsers("signin",username,password);
        call.enqueue(new Callback<UserResponse>() {
            @Override
            public void onResponse(Call<UserResponse> call, Response<UserResponse> response) {
                UserResponse result = response.body();
                Log.d("res",""+result.getData());

            }

            @Override
            public void onFailure(Call<UserResponse> call, Throwable t) {
                Log.d("res",""+t.getMessage());

            }
        });
    }

Model class

public class User {

    String id;
    String username;
    String email;
    String access_token;
    String refresh_token;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAccess_token() {
        return access_token;
    }

    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }

    public String getRefresh_token() {
        return refresh_token;
    }

    public void setRefresh_token(String refresh_token) {
        this.refresh_token = refresh_token;
    }

}

UserResponse.java

public class UserResponse {
    List<User> data;

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

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

}

Interface

public interface WebserviceAPI {
    @FormUrlEncoded
    @POST("auth")
    Call<UserResponse> getUsers(@Field("module_action") String signin ,@Field("username") String username,@Field("password") String password);
}

Response from server side : PHP

$response = ['status' => true,
            'message' => "Successfully logged in",
            'data' => [
              'access_token' => $accessToken,
              'refresh_token' => $refreshToken
            ],
          ];
            $this->returnJson($response, 200);

when i run in Postman,response is like below

enter image description here

--------Update-----------

some response contain only status and message.

response eg :

{
    "status": false,
    "message": "Inactive User"
}

then i want to get message.

i have edited UserResponse as below and tried to get message.then showing java.lang.NullPointerException at com.android.app.myapp.Login$3.onResponse(Login.java:92)

 public class UserResponse {
        @SerializedName("status")
        @Expose
        private String status;
    
        @SerializedName("message")
        @Expose
        private String message;
    
        User data;
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public User getData() {
            return data;
        }
    
        public void setData(User data) {
            this.data = data;
        }
    
    }

public void getUser(String username,String password){

        WebserviceAPI apiService =retrofit.create(WebserviceAPI.class);
        Call<UserResponse> call = apiService.getUsers("signin",username,password);
        call.enqueue(new Callback<UserResponse>() {
            @Override
            public void onResponse(Call<UserResponse> call, Response<UserResponse> response) {
                UserResponse result = response.body();
                //User data = result.getData();
                Log.d("userresponse",""+result.getMessage());
              
            }

            @Override
            public void onFailure(Call<UserResponse> call, Throwable t) {
                Log.d("res",""+t.getMessage());

            }
        });
    }

Upvotes: 0

Views: 415

Answers (2)

silverFoxA
silverFoxA

Reputation: 4659

The error says it all Expected BEGIN_ARRAY but was BEGIN_OBJECT -ANDROID RETROFIT2 i.e the response or the JSON received is an Object where you are trying to access it as an array.

Change your server code to

$response[] = array('status' => true,
            'message' => "Successfully logged in",
            'data' => [
              'access_token' => $accessToken,
              'refresh_token' => $refreshToken
            ],
          );

echo json_encode($response);

Expected response is

[{"status":true,"message":"Successfully logged in","data":{"access_token":null,"refresh_token":null}}]

Which is an array

Upvotes: 0

Nikhil Gupta
Nikhil Gupta

Reputation: 881

In your Postman response data field is coming as a JSON Object, not as a JSON array. If this is the case and you are using "data" field as a list in your UserResponse model, it will not be able to map it. This is the issue i think. To solve it you can use below UserResponse data model :

public class UserResponse {
    User data;

    public User getData() {
        return data;
    }

    public void setData(User data) {
        this.data = data;
    }

}

Upvotes: 1

Related Questions