Retrofit多响应处理问题:API成功/失败响应无法用POJO适配
这个坑我之前踩过!你的问题本质是API返回的成功/失败响应结构不统一——成功时返回业务数据,失败时返回完全不同的错误格式,导致你现有的POJO只能适配成功场景,失败时直接触发JSON解析异常跳去onFailure,根本拿不到错误消息。下面给你两种解决方案:
1. 最优方案:统一API响应结构
这是最稳妥的做法,跟后端沟通让他们返回统一的外层响应格式,不管成功失败都遵循同一个结构:
// 成功响应 { "code": 200, "message": "操作成功", "data": { /* 你的业务数据,比如用户信息、列表等 */ } } // 失败响应 { "code": 400, "message": "参数错误", "data": null }
然后创建一个通用的BaseResponse父类来适配这个结构:
public class BaseResponse<T> { private int code; private String message; private T data; // 生成getter、setter方法 // 自定义判断成功的方法,根据后端约定的成功码调整 public boolean isSuccess() { return code == 200; } }
原来的业务POJO(比如UserInfoResponse)作为泛型T传入,修改你的网络请求接口(以Retrofit为例):
@GET("user/info") Call<BaseResponse<UserInfoResponse>> getUserInfo();
最后在回调里就能同时处理成功和失败场景了:
call.enqueue(new Callback<BaseResponse<UserInfoResponse>>() { @Override public void onResponse(Call<BaseResponse<UserInfoResponse>> call, Response<BaseResponse<UserInfoResponse>> response) { if (response.isSuccessful()) { BaseResponse<UserInfoResponse> baseResp = response.body(); if (baseResp.isSuccess()) { // 处理成功数据 UserInfoResponse userData = baseResp.getData(); } else { // 这里直接拿到失败的错误消息! String errorMsg = baseResp.getMessage(); showErrorToast(errorMsg); } } else { // 处理HTTP状态码非200的情况(比如404、500),解析错误体 try { String errorJson = response.errorBody().string(); BaseResponse<?> errorResp = new Gson().fromJson(errorJson, BaseResponse.class); String errorMsg = errorResp.getMessage(); showErrorToast(errorMsg); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Call<BaseResponse<UserInfoResponse>> call, Throwable t) { // 这里只处理真正的网络异常:无网络、连接超时、DNS解析失败等 showErrorToast("网络连接失败,请稍后重试"); } });
2. 妥协方案:无法修改API时的异常捕获
如果后端没法改API格式,那就只能在onFailure里捕获解析异常,手动解析错误响应体:
首先创建一个适配失败响应的ErrorResponse类:
public class ErrorResponse { private int code; private String message; // 生成getter、setter方法 }
然后在onFailure里判断异常类型,解析错误体:
@Override public void onFailure(Call<UserInfoResponse> call, Throwable t) { // 捕获JSON解析异常,尝试解析错误响应 if (t instanceof HttpException) { HttpException httpException = (HttpException) t; ResponseBody errorBody = httpException.response().errorBody(); if (errorBody != null) { try { String errorJson = errorBody.string(); ErrorResponse errorResp = new Gson().fromJson(errorJson, ErrorResponse.class); // 拿到失败消息 String errorMsg = errorResp.getMessage(); showErrorToast(errorMsg); } catch (IOException e) { e.printStackTrace(); showErrorToast("解析错误失败"); } } } else { // 处理其他网络异常 showErrorToast("网络连接失败,请稍后重试"); } }
这种方式虽然能解决问题,但不够优雅——如果后端修改了失败响应格式,你的ErrorResponse就得跟着改,维护成本高,还是优先推荐统一API响应结构。
内容的提问来源于stack exchange,提问作者Yehia Ahmad
相关产品推荐
相关产品推荐

