Dandy
Dandy

Reputation: 23

Why does Gson expect the beginning array but gets an object instead?

I'm using this JSON which stores some articles with Retrofit, but I have an error:

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2

Here's my code:

RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint("http://www.example.com/")
        .setLogLevel(RestAdapter.LogLevel.FULL)
        .build();

Flow flowservice = restAdapter.create(Flow.class);

flowservice.getArticles("55ec320b066ee7ae08360f12", new Callback<List<String>>() {

    @Override
    public void success(List<String> objects, Response response) {
        textView.setText(objects.get(0));
    }

    @Override
    public void failure(RetrofitError error) {
        textView.setText(error.getMessage());
    }
});

And I use this POJO:

public class Article implements Serializable {
    private int remoteId;
    private String title;
    private String imageUrl;
    private String content;
    private int viewsCount;
    private int commentsCount;
    private int likesCount;
    private int categoryId;
    private String authorName;
    private boolean liked;

    // getters and setters removed
}

And a sample JSON:

{  
   "success":true,
   "errorCode":0,
   "articles":[  
      {  
         "remoteId":0,
         "title":"Nam viverra vulputate lacus nec pellentesque. Nam viverra vulputate lacus nec pellentesque.",
         "imageUrl":"/articles/armatis.png",
         "content":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas interdum tempus ultrices. Ut quis tellus molestie, ornare mi non, fermentum nisl. Sed vitae ultricies metus. Vivamus aliquam metus enim, ut fringilla justo molestie et. Maecenas nec ligula neque. Mauris vel cursus risus. Suspendisse ut nulla porta, congue nulla sit amet.",
         "viewsCount":235,
         "commentsCount":6,
         "likesCount":18,
         "categoryId":1,
         "authorName":"Sébastien Gabory",
         "liked":false
      },
      {  
         "remoteId":1,
         "title":"Nam viverra vulputate lacus nec pellentesque.",
         "imageUrl":"/articles/armatis.png",
         "content":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas interdum tempus ultrices. Ut quis tellus molestie, ornare mi non, fermentum nisl. Sed vitae ultricies metus. Vivamus aliquam metus enim, ut fringilla justo molestie et. Maecenas nec ligula neque. Mauris vel cursus risus. Suspendisse ut nulla porta, congue nulla sit amet.",
         "viewsCount":18,
         "commentsCount":6,
         "likesCount":25,
         "categoryId":1,
         "authorName":"Sébastien Gabory",
         "liked":false
      }
   ]
}

Flow class:

public interface Flow {
    @GET("/v2/{json}")
    void getArticles (@Path("json") String json ,Callback<List<Article>> callback);
}

Upvotes: 1

Views: 247

Answers (1)

stkent
stkent

Reputation: 20128

GSON is trying to convert your JSON response directly into a list of articles. However, your list of articles is actually nested one level deep inside an outer JSON object. When GSON tries to convert this outer object into a JSON array (for eventual conversion to a Java List), it therefore throws the error you see:

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2

One fix for this would be to make a new POJO representing the entire JSON response. For example:

public class ArticleListWrapper implements Serializable {
    private boolean success;
    private double errorCode;
    private List<Article> articles;

    // getters and setters, etc.
}

Then your Flow class would be updated as follows:

@GET("/v2/{json}")
void getArticleListWrapper (@Path("json") String json, Callback<ArticleListWrapper> callback);

GSON should then be able to deserialize the JSON response into an ArticleListWrapper object properly. You would be able to retrieve the list of articles in the callback by accessing the articles field of this ArticleListWrapper object.

Upvotes: 3

Related Questions