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前面有额外的字符(比如
\ufeffBOM头、空格、换行),那这些字符会导致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. 完善请求成功后的判断逻辑
在MainActivity的onResponse方法中,先判断请求是否成功,避免直接取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




