使用Retrofit调用自研REST接口无法接收JSON数据求助
排查Retrofit无法解析JSON响应的问题
看起来你遇到的核心矛盾是:服务端返回的Content-Type显示为text/html,但你确认接口应该返回JSON,这直接导致Retrofit的Gson转换器无法正确解析数据。我帮你梳理几个关键排查方向:
1. 优先确认服务端的响应头设置
这是最常见的触发原因!你的PHP接口api_get_all_chats.php必须在输出JSON数据之前,明确设置正确的Content-Type响应头:
// 一定要放在echo JSON之前 header('Content-Type: application/json'); // 然后输出JSON内容 echo json_encode($your_data_array);
如果服务端没有设置这个头,Web服务器会默认返回text/html,Retrofit的Gson转换器会直接跳过解析,导致response.body()为null甚至触发解析异常。
2. 仔细查看HttpLoggingInterceptor的日志细节
你已经添加了日志拦截器,一定要重点关注这几个日志内容:
- 响应头:确认
Content-Type字段的实际值,是不是真的是text/html - 响应体:检查返回的内容是不是纯JSON,有没有夹杂HTML标签(比如服务端报错的404/500页面、调试用的HTML输出)
如果响应体是HTML错误页面,说明你的请求可能存在路径错误、参数不匹配等问题,需要先解决服务端的请求匹配问题。
3. 验证请求方式与参数是否匹配服务端要求
你当前用的是@FormUrlEncoded+@POST+@Field,这会发送x-www-form-urlencoded格式的请求体。需要确认服务端的接收逻辑:
- 如果服务端是通过
$_POST['id']获取参数,那当前写法是正确的 - 如果服务端期望的是JSON格式的请求体,那需要修改接口定义:
// 去掉@FormUrlEncoded,改用@Body传递参数 @POST("api_get_all_chats.php") Call<List<Chat>> getChats(@Body Map<String, String> idMap); // 调用时传入参数:new HashMap<>(){{put("id", u.getUserInfo().getUserId());}}
4. 处理Content-Type不匹配的权宜之计(不推荐优先使用)
如果暂时无法修改服务端的Content-Type设置,可以自定义ConverterFactory,强制把text/html类型的响应当作JSON来解析:
retrofit = new Retrofit.Builder() .baseUrl("http://MYIP/emob%20projekat/api/") .addConverterFactory(new Converter.Factory() { private final Gson gson = new Gson(); @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return (ResponseBody responseBody) -> { // 将text/html响应转换为JSON格式解析 String jsonContent = responseBody.string(); responseBody.close(); return gson.fromJson(jsonContent, type); }; } }) .client(client) .build();
注意这只是临时解决方案,长期来看还是让服务端正确设置Content-Type更规范。
5. 检查BaseUrl的正确性
你的BaseUrl包含%20(空格的URL编码),可以确认下服务端的实际路径是不是emob projekat/api/。如果路径里没有空格,那可能是BaseUrl写错了,导致请求到错误的资源(返回HTML 404页面)。
内容的提问来源于stack exchange,提问作者aratata
相关产品推荐
相关产品推荐

