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

从HttpURLConnection迁移至Retrofit2遇到Gson解析异常问题

解决Retrofit2 + GsonConverterFactory 遇到的 Expected BEGIN_OBJECT 错误

我之前也碰到过几乎一模一样的问题——旧代码手动用GZipInputStream解压能正常解析JSON,换成Retrofit就直接报格式错误,核心原因大概率是Retrofit没有自动处理Gzip压缩的响应,导致Gson拿到的是原始压缩字节流,根本不是合法的JSON字符串,自然会触发"Expected BEGIN_OBJECT"的报错。下面给你一步步排查解决:

1. 先确认服务器响应的压缩状态

先用Postman或者浏览器调用目标接口,检查响应头里是否存在 Content-Encoding: gzip。如果有这个字段,说明服务器返回的是Gzip压缩后的内容,这时候Retrofit必须配置解压逻辑才能正确读取JSON。

2. 给OkHttpClient配置Gzip解压支持

Retrofit依赖OkHttp,OkHttp本身有内置的Gzip处理能力,但如果你自定义了OkHttpClient实例,可能需要显式配置确保生效:

OkHttpClient client = new OkHttpClient.Builder()
    // 显式添加请求头,告诉服务器我们接受Gzip压缩的响应
    .addInterceptor(chain -> {
        Request compressedRequest = chain.request().newBuilder()
                .header("Accept-Encoding", "gzip")
                .build();
        return chain.proceed(compressedRequest);
    })
    // OkHttp 4+ 可以直接用内置的Gzip请求拦截器,写法更简洁:
    // .addInterceptor(new GzipRequestInterceptor())
    .build();

然后把这个配置好的client传给Retrofit:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("你的服务器基础地址")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

3. 检查实体类与JSON结构的匹配度

虽然旧代码能手动解析,但要确保你的实体类完全对应JSON的结构:

  • 如果JSON是{...}格式的单个对象,接口返回类型必须是Call<YourEntity>,不能写成Call<List<YourEntity>>
  • 字段名要和JSON键一致,或者用@SerializedName注解做映射,比如:

假设你的JSON是:

{
  "user_id": 1001,
  "user_name": "Mike"
}

对应的实体类应该是:

public class User {
    @SerializedName("user_id")
    private int userId;
    @SerializedName("user_name")
    private String userName;
    
    // 记得添加getter/setter方法
}

4. 排查拦截器的执行顺序

如果你还添加了日志拦截器(比如HttpLoggingInterceptor),一定要把它放在Gzip拦截器之后,避免日志拦截器提前读取压缩流,导致后续解压逻辑无法正常获取数据。

最后验证

配置完成后,用日志拦截器打印响应体,如果你能看到以{开头的正常JSON字符串,说明解压已经生效,Gson就能自动映射到实体类了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:19:04