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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:33:32