You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Retrofit请求API遇JSON格式错误,寻求有效解决方案

解决Retrofit解析JSON时的"Use JsonReader.setLenient(true)"错误

你已经在Gson里设置了setLenient()但还是遇到这个错误,这说明问题不是JSON格式的小问题,而是服务器返回的内容可能根本不是你预期的JSON,或者在JSON前面有额外的干扰字符(比如BOM头、空格、HTML错误页面内容)。下面是具体的排查和解决步骤:

1. 先确认服务器实际返回的内容

首先用Postman、curl或者浏览器直接访问http://stock.adverscribe.in/api/controllers/getMenu,看看返回的是不是你贴的那段标准JSON:

  • 如果返回的是HTML页面(比如404、500错误页),说明你的接口路径有问题,检查BaseUrl和接口注解的拼接是否正确;
  • 如果返回的JSON前面有额外的字符(比如\ufeff BOM头、空格、换行),那这些字符会导致Gson解析失败,即使开启了lenient也没用。

2. 添加响应拦截器清理返回内容

如果确认返回的JSON前面有干扰字符,可以给OkHttpClient添加一个拦截器,提前清理响应内容:

修改你的ApiClient类,添加拦截器并设置到Retrofit中:

public class ApiClient {
    public static final String BASE_URL = "http://stock.adverscribe.in/api/controllers/";
    private static Retrofit retrofit = null;

    public static Retrofit getClient() {
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        // 构建带有拦截器的OkHttpClient
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Response originalResponse = chain.proceed(chain.request());
                        String rawResponse = originalResponse.body().string();

                        // 移除UTF-8 BOM头(如果存在)
                        if (rawResponse.startsWith("\ufeff")) {
                            rawResponse = rawResponse.substring(1);
                        }
                        // 去除开头的空格、换行等无效字符
                        rawResponse = rawResponse.trim();

                        // 重新构建响应体
                        return originalResponse.newBuilder()
                                .body(ResponseBody.create(originalResponse.body().contentType(), rawResponse))
                                .build();
                    }
                })
                .build();

        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client) // 设置自定义的OkHttpClient
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }
        return retrofit;
    }
}

3. 完善请求成功后的判断逻辑

MainActivityonResponse方法中,先判断请求是否成功,避免直接取response.body()导致空指针,同时打印错误响应内容方便排查:

@Override
public void onResponse(Call<MenuResponse> call, Response<MenuResponse> response) {
    if (response.isSuccessful()) {
        // 请求成功,处理返回数据
        MenuResponse menuResponse = response.body();
        if (menuResponse != null) {
            int code = menuResponse.getCode();
            Toast.makeText(MainActivity.this, "" + code, Toast.LENGTH_SHORT).show();
        }
    } else {
        // 请求失败,打印错误响应内容
        try {
            String errorContent = response.errorBody().string();
            Log.e("API_ERROR", "错误响应内容: " + errorContent);
            Toast.makeText(MainActivity.this, "请求失败: " + errorContent, Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "请求失败,无法获取错误信息", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 检查接口路径是否正确

确认你的BASE_URL@GET("getMenu")拼接后的完整路径是否正确,比如有没有多了斜杠或者少了路径部分,导致服务器返回错误页面而非JSON。


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

火山引擎 最新活动