Retrofit调用接口报java.lang.IllegalStateException:预期对象却得数组
解决Retrofit请求时的
java.lang.IllegalStateException异常 咱先把这个异常的本质说透:你用Retrofit声明的返回数据类型,和接口实际返回的JSON结构完全不匹配。具体到你的报错Expected BEGIN_OBJECT but was BEGIN_ARRAY,意思就是Gson解析器本来以为要解析一个JSON对象(用{}包裹的结构),结果收到的却是一个JSON数组(用[]包裹的结构),直接懵圈报错了。
下面给你一步步排查解决的方法:
1. 先搞清楚接口返回的JSON到底是什么结构
直接访问你提供的接口链接,看看返回的内容是下面哪种:
- 第一种:纯数组结构(比如
[{"classId":1, "className":"数学"}, ...]) - 第二种:包含数组的对象结构(比如
{"code":200, "data": [{"classId":1, ...}]})
这一步是关键,搞清楚结构才能针对性改代码。
2. 针对不同结构修改代码
情况一:接口返回纯JSON数组
如果接口返回的是纯数组,那你代码里Call<List<AllRespoClass>>的声明是对的,但问题大概率出在AllRespoClass的定义上:
- 检查字段类型:比如JSON里某个字段是数组(比如
"students": [{"name":"张三"}]),但你在AllRespoClass里把它定义成了单个对象(private Student students;),这时候就会报同样的错,要改成private List<Student> students;。 - 检查字段名匹配:如果JSON键是
class_id,而你的实体类字段是classId,记得加@SerializedName注解映射:@SerializedName("class_id") private int classId; - 别忘了给实体类加无参构造方法,Gson解析时需要这个。
正确的AllRespoClass示例:
public class AllRespoClass { @SerializedName("class_id") private int classId; @SerializedName("class_name") private String className; public AllRespoClass() {} // Getter和Setter方法 public int getClassId() { return classId; } public void setClassId(int classId) { this.classId = classId; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } }
情况二:接口返回包含数组的JSON对象
如果接口返回的是带外层的对象(比如有status、data这类字段),那你直接用List<AllRespoClass>就不对了,得定义一个外层实体类来包裹整个结构:
先写外层类ClassResponse:
public class ClassResponse { private String status; @SerializedName("classes") private List<AllRespoClass> classList; public ClassResponse() {} // Getter和Setter public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public List<AllRespoClass> getClassList() { return classList; } public void setClassList(List<AllRespoClass> classList) { this.classList = classList; } }
然后把Retrofit的Call改成:
Call<ClassResponse> allInputDataApiCall = apiGet.getDataInput();
最后修改回调逻辑:
allInputDataApiCall.enqueue(new Callback<ClassResponse>() { @Override public void onResponse(Call<ClassResponse> call, Response<ClassResponse> response) { if (response.isSuccessful() && response.body() != null) { List<AllRespoClass> allClasses = response.body().getClassList(); // 这里就可以正常处理数据了 } } @Override public void onFailure(Call<ClassResponse> call, Throwable t) { // 处理请求失败的情况 t.printStackTrace(); } });
3. 最后再检查两个细节
- 确保你的Retrofit实例配置了Gson转换器,没有这个的话解析会出问题:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://elearnup.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); - 如果接口返回的JSON有嵌套结构,一定要把每个层级的实体类都定义正确,不能漏。
内容的提问来源于stack exchange,提问作者Manoj Budha Ayer
相关产品推荐
相关产品推荐

