You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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),数据类型不匹配导致解析失败。

解决方案

有两种可行处理方式:

  1. 适配后端返回的数组格式
    修改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 );
          }
      });
    
  2. 要求后端调整返回格式
    如果后端支持修改,让其根据ID返回单个Students对象的JSON格式(而非数组),现有代码无需修改即可正常运行。

内容的提问来源于stack exchange,提问作者KMD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:14:58