使用Retrofit按ID获取数据时遇JsonSyntaxException报错求助
问题:Retrofit根据ID获取学生数据触发JsonSyntaxException错误
报错信息
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
学生实体类代码
public class Students implements Parcelable { private int id; @SerializedName("first_name") private String firstName; @SerializedName("last_name") private String lastName; private String course; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getCourse() { return course; } public void setCourse(String course) { this.course = course; } public String getScore() { return score; } public void setScore(String score) { this.score = score; } private String score; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.id); dest.writeString(this.firstName); dest.writeString(this.lastName); dest.writeString(this.course); dest.writeString(this.score); } public void readFromParcel(Parcel source) { this.id = source.readInt(); this.firstName = source.readString(); this.lastName = source.readString(); this.course = source.readString(); this.score = source.readString(); } public Students() { } protected Students(Parcel in) { this.id = in.readInt(); this.firstName = in.readString(); this.lastName = in.readString(); this.course = in.readString(); this.score = in.readString(); } public static final Parcelable.Creator<Students> CREATOR = new Parcelable.Creator<Students>() { @Override public Students createFromParcel(Parcel source) { return new Students(source); } @Override public Students[] newArray(int size) { return new Students[size]; } }; }
Retrofit接口代码
public interface Api { @GET(url) Single<Students> getStudent(@Query("id") int id); }
MainActivity请求代码
Retrofit retrofit = new Retrofit.Builder() .baseUrl(URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .build(); Api api = retrofit.create(Api.class); api.getStudent(339).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver<Students>() { @Override public void onSubscribe(@NonNull Disposable d) { } @Override public void onSuccess(@NonNull Students students) { Log.i(TAG, "onSuccess: "+students); } @Override public void onError(@NonNull Throwable e) { Log.e(TAG, "onError: "+e ); } });
错误原因及解决方案
错误原因
报错核心是:Gson期望解析单个Students对象(对应JSON的BEGIN_OBJECT),但后端接口实际返回的是包含学生数据的JSON数组(对应BEGIN_ARRAY),数据类型不匹配导致解析失败。
解决方案
有两种可行处理方式:
适配后端返回的数组格式
修改Retrofit接口的返回类型为Single<List<Students>>,同时调整订阅回调的接收逻辑:// 修改后的Api接口 public interface Api { @GET(url) Single<List<Students>> getStudent(@Query("id") int id); }// 修改后的订阅代码 api.getStudent(339) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new SingleObserver<List<Students>>() { @Override public void onSubscribe(@NonNull Disposable d) {} @Override public void onSuccess(@NonNull List<Students> studentsList) { // 根据ID查询应仅返回一条数据,直接取数组第一个元素 if (!studentsList.isEmpty()) { Students student = studentsList.get(0); Log.i(TAG, "onSuccess: "+student); } } @Override public void onError(@NonNull Throwable e) { Log.e(TAG, "onError: "+e ); } });要求后端调整返回格式
如果后端支持修改,让其根据ID返回单个Students对象的JSON格式(而非数组),现有代码无需修改即可正常运行。
内容的提问来源于stack exchange,提问作者KMD
相关产品推荐
相关产品推荐

