Maxime M.
Maxime M.

Reputation: 25

Android retrofit parsing JSON Expected BEGIN_OBJECT but was BEGIN_ARRAY

I'm trying to use retrofit 2 to parse a json array :

[{"question":"question 1"},{"question":"question 2"}]

Here is the main activity of my project :

package maxime.mysqltest;

import android.graphics.Movie;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    private final static int idForm = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Questionable questionService =
                ApiClient.getClient().create(Questionable.class);

        Call<QuestionList> call = questionService.getQuestions(idForm);
        call.enqueue(new Callback<QuestionList>() {
            @Override
            public void onResponse(Call<QuestionList>call, Response<QuestionList> response) {
                List<Question> questions = response.body().getQuestions();
                Log.d(TAG, "Number of questions received: " + questions.size());
            }

            @Override
            public void onFailure(Call<QuestionList>call, Throwable t) {
                // Log error here since request failed
                Log.e(TAG, t.toString());
            }
        });
    }
}

I created a class to access my page on the MAMP server :

public class ApiClient {

    public static final String BASE_URL = "http://*myIP*:8888";
    private static Retrofit retrofit = null;


    public static Retrofit getClient() {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

I also have two classes for the object that I try to parse :

public class Question {

    private final String question;


    public Question(String question)
    {
        this.question=question;
    }

}

public class QuestionList {

    private List<Question> questions = new ArrayList<>();

    public QuestionList(List<Question> questions)
    {
        this.questions=questions;
    }

    public List<Question> getQuestions() {
        return questions;
    }
}

and finally my interface :

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface Questionable {

    @GET("/takeQuestions.php")
    Call<QuestionList> getQuestions(@Query("idForm") int idForm);
}

When I run the application the following error appeared :

E/MainActivity: com.google.gson.JsonSyntaxException: 
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was 
BEGIN_ARRAY at line 1 column 2 path $

I searched on the internet but I can't find a solution to my problem...

Upvotes: 1

Views: 558

Answers (1)

David Medenjak
David Medenjak

Reputation: 34532

Gson expected an Object but it received an Array.

This is a plain json array with 2 objects:

[{"question":"question 1"},{"question":"question 2"}]

This is an object that contains a list questions that has the questions in it.

public class QuestionList {

  private List<Question> questions = new ArrayList<>();

}

Which would look like:

{
  "questions" : [{"question":"question 1"},{"question":"question 2"}]
}

So when you tell retrofit that you expect a Call<QuestionList> Gson expects the above Json, which is not the same as the one on top. It is a list "wrapped" inside an object.


Your call object should look like this:

Call<Question[]> getQuestions()
  // or
Call<List<Question>> getQuestions()

either of which is an actual list / array of Question.

Upvotes: 1

Related Questions