Android Java使用Retrofit2如何处理服务端返回的不一致响应
处理方案
你不需要为两种响应创建完全独立的外层数据类,当前解析报错的核心原因是服务端接口设计不规范:同一个result字段,成功时返回对象、失败时返回空数组,序列化库默认无法自动识别转换同名字段的不同类型。
推荐实现(通用可复用)
抽离通用响应基类,自定义反序列化逻辑适配多类型字段,一次配置所有接口都能复用:
- 定义泛型基类承接所有响应的公共字段
public class BaseResponse<T> implements Serializable { private boolean status; private T result; private String message; // 多数接口失败时会返回错误提示,可按需添加 public boolean isSuccess() { return status; } public T getResult() { return result; } public String getMessage() { return message; } }
- 将原本嵌套在
User类里的ResultModel抽为独立的业务实体类,注意字段类型和服务端返回匹配:服务端返回的id是数值类型,不要定义为String,避免类型转换错误
public class UserInfo implements Serializable { private int id; private String name; private String email; }
- 自定义Gson反序列化适配器,解析时先判断
status值,再决定如何解析result字段
public class ResponseDeserializer<T> implements JsonDeserializer<BaseResponse<T>> { private final Class<T> resultClazz; public ResponseDeserializer(Class<T> resultClazz) { this.resultClazz = resultClazz; } @Override public BaseResponse<T> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { BaseResponse<T> response = new BaseResponse<>(); JsonObject obj = json.getAsJsonObject(); boolean status = obj.get("status").getAsBoolean(); response.status = status; // 解析错误提示 if (obj.has("message") && !obj.get("message").isJsonNull()) { response.message = obj.get("message").getAsString(); } // 仅成功状态下解析result为业务对象,失败时result是空数组直接忽略,赋值为null if (status) { JsonElement resultEle = obj.get("result"); if (resultEle != null && resultEle.isJsonObject()) { response.result = context.deserialize(resultEle, resultClazz); } } return response; } }
- 给Retrofit配置Gson时注册该适配器,接口定义直接返回对应泛型的基类即可
Gson gson = new GsonBuilder() .registerTypeAdapter( TypeToken.getParameterized(BaseResponse.class, UserInfo.class).getType(), new ResponseDeserializer<>(UserInfo.class) ) .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("你的接口基地址") .addConverterFactory(GsonConverterFactory.create(gson)) .build(); // 接口定义 interface ApiService { @GET("user/info") Call<BaseResponse<UserInfo>> getUserInfo(); }
快速临时方案(适合小型项目/少量接口)
如果不想写自定义适配器,可以把result字段定义为JsonElement类型,拿到响应后手动判断类型转换:
public class UserResponse implements Serializable { private boolean status; private JsonElement result; public boolean isSuccess() { return status; } public UserInfo getResult() { if (status && result.isJsonObject()) { return new Gson().fromJson(result, UserInfo.class); } return null; } }
这种方式实现简单,但每个接口都要写重复的转换逻辑,不适合接口多的项目。
补充说明
- 不建议分别创建成功、失败两套响应类:Retrofit每个接口只能绑定固定的响应类型,无法根据返回内容自动切换解析类,反而会增加不必要的复杂度。
- 最优方案是和服务端沟通统一字段类型:失败场景下
result返回null而非空数组,从根源避免类型不匹配问题。
内容的提问来源于stack exchange,提问作者YeJong Choe
相关产品推荐
相关产品推荐

