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

Android使用Retrofit解析JSON出现Expected BEGIN_OBJECT错误如何解决

错误原因分析

该报错核心含义是Gson解析时预期根节点为JSON对象,但实际接收到的根节点是字符串类型,结合提供的代码,可能的触发原因如下:

  • 接口实际返回内容不是Postman拿到的JSON结构,服务端在参数错误、鉴权失败时直接返回了纯文本错误提示,没有包裹JSON结构
  • 代码调用接口时传的参数和Postman不一致,尤其是apiKey、时间参数(代码里传的请求时间是0500,Postman拿到的响应里baseTime是1100,参数不匹配会触发服务端返回非JSON的错误响应)
  • 服务端开启了UA校验、反爬规则,移动端请求时返回了HTML/纯文本的拦截提示,而非正常JSON
  • 次要排查项:@Expose注解未配合Gson配置生效,不过该问题不会触发根节点的解析错误
解决步骤
  1. 先打印接口返回的原始响应内容,确认实际返回的结构
    给Retrofit添加日志拦截器,查看完整的请求和响应内容,首先添加依赖(如未添加):
implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0'

修改RetrofitService的代码,添加日志拦截器:

public class RetrofitService {
    public Retrofit getRetroInstance(String baseUrl){
        // 添加日志拦截器打印完整请求响应
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build();

        Gson gson = new GsonBuilder()
                .setLenient()
                .excludeFieldsWithoutExposeAnnotation() // 配合@Expose注解过滤不需要序列化的字段
                .create();

        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
}
  1. 校验请求参数和Postman完全一致:确认代码里传的apiKey、请求日期、请求时间参数和Postman调用时用的参数完全相同,避免参数错误导致服务端返回非JSON响应
  2. 如果确认服务端有时会返回字符串类型的错误响应,可以先把Retrofit的响应类型改成ResponseBody,手动判断响应格式再做解析:
    修改接口请求的返回类型为Call<ResponseBody>,收到响应后先转成字符串,判断是JSON结构再用Gson转成ShortWeather对象,否则直接处理错误字符串:
Call<ResponseBody> call = MaAPI.getShortWeather("你的正式apiKey", 50,1,"JSON","20210904","1100",55,127);
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if(response.isSuccessful() && response.body() != null){
            try {
                String responseStr = response.body().string();
                Log.d(TAG, "原始响应: " + responseStr);
                // 手动解析响应
                Gson gson = new GsonBuilder().setLenient().create();
                ShortWeather weather = gson.fromJson(responseStr, ShortWeather.class);
                data.postValue(weather);
            } catch (Exception e) {
                e.printStackTrace();
                Log.d(TAG, "解析失败,原始响应不是合法JSON");
            }
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.d(TAG,"onFailure : "+t.getMessage());
    }
});
  1. 额外校验:你定义的DTO类里已经通过@SerializedName完成了JSON字段和类字段的映射,这部分逻辑正确,不需要修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:27:03