Retrofit Expected BEGIN_OBJECT but was BEGIN_ARRAY

Jezer Crespo picture Jezer Crespo · Jun 11, 2014 · Viewed 74.6k times · Source

I'm fairly new to JSON parsing, I'm using the Retrofit library of Square and ran into this problem.

I'm trying to parse this JSON reponse:

[
      {
        "id": 3,
        "username": "jezer",
        "regid": "oiqwueoiwqueoiwqueoiwq",
        "url": "http:\/\/192.168.63.175:3000\/users\/3.json"
      },
      {
        "id": 4,
        "username": "emulator",
        "regid": "qwoiuewqoiueoiwqueoq",
        "url": "http:\/\/192.168.63.175:3000\/users\/4.json"
      },
      {
        "id": 7,
        "username": "test",
        "regid": "ksadqowueqiaksj",
        "url": "http:\/\/192.168.63.175:3000\/users\/7.json"
      }
]

Here are my models:

public class Contacts {

    public List<User> contacts;

}

...

public class User {

    String username;
    String regid;

    @Override
    public String toString(){
        return(username);
    }  

}

my Interface:

public interface ContactsInterface {

    @GET("/users.json")
    void contacts(Callback<Contacts> cb);

}

my success method:

@Override
public void success(Contacts c, Response r) {
    List<String> names = new ArrayList<String>();
    for (int i = 0; i < c.contacts.size(); i++) {
        String name = c.contacts.get(i).toString();
        Log.d("Names", "" + name);
        names.add(name);
    }
    ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, names);
    mSentTo.setAdapter(spinnerAdapter);
}

When I use it on my success method it throws the error

Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column2

What is wrong here?

Answer

Jake Wharton picture Jake Wharton · Jun 11, 2014

Right now you are parsing the response as if it was formatted like this:

{
  "contacts": [
    { .. }
  ]
}

The exception tells you this in that you are expecting an object at the root but the real data is actually an array. This means you need to change the type to be an array.

The easiest way is to just use a list as the direct type in the callback:

@GET("/users.json")
void contacts(Callback<List<User>> cb);