Retrofit动态JSON响应类型变更适配问题求助
解决Retrofit中动态JSON字段(int/String兼容)的适配问题
这个问题我之前也碰到过,确实挺头疼的——Gson默认的类型匹配太严格,遇到这种同一字段时而返回int、时而返回String的JSON响应,直接就会抛出类型转换异常。不过不用改Rest Adapter,咱们在现有ApiClient架构的基础上,通过自定义Gson的类型适配器就能完美解决,给你两种可行的方案:
方案一:全局适配所有int/Integer字段
这种方案适合你希望所有涉及int类型的Model字段都能自动兼容String类型的场景,只需要修改ApiClient中的Gson配置即可:
1. 自定义类型适配器
先写一个TypeAdapter,用来处理int和String之间的自动转换:
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; public class IntStringTypeAdapter extends TypeAdapter<Integer> { @Override public void write(JsonWriter out, Integer value) throws IOException { // 写数据时直接输出int值即可 out.value(value); } @Override public Integer read(JsonReader in) throws IOException { // 读取数据时判断当前字段的类型 if (in.peek() == JsonToken.STRING) { // 如果是String类型,尝试转成int String stringValue = in.nextString(); try { return Integer.parseInt(stringValue); } catch (NumberFormatException e) { // 转换失败时可以返回默认值,或者根据业务需求抛异常 return 0; // 这里的默认值你可以自己调整 } } else if (in.peek() == JsonToken.NULL) { // 如果字段是null,返回null或者默认值 in.nextNull(); return null; } else { // 原本的int类型,直接读取 return in.nextInt(); } } }
2. 修改ApiClient的Gson配置
把自定义的TypeAdapter注册到Gson实例中,替换原来默认的Gson:
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class ApiClient { public static final String BASE_URL = "http:***********"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit == null) { // 创建自定义Gson实例,注册我们的类型适配器 Gson customGson = new GsonBuilder() .registerTypeAdapter(Integer.class, new IntStringTypeAdapter()) .registerTypeAdapter(int.class, new IntStringTypeAdapter()) // 处理基本类型int .create(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create(customGson)) // 使用自定义Gson .build(); } return retrofit; } }
这样修改后,所有Model中的int/Integer字段都会自动兼容JSON中的String类型,不用逐个修改Model类。
方案二:针对单个Model字段适配
如果你只需要处理某几个特定的字段,不想全局生效,可以用@JsonAdapter注解直接在Model字段上指定适配器:
import com.google.gson.annotations.JsonAdapter; public class YourModel { // 只给这个字段指定适配器 @JsonAdapter(IntStringTypeAdapter.class) private int targetField; // 其他字段保持原来的类型 private String otherField; // getter和setter方法 }
这种方式更灵活,不会影响其他无关字段的解析逻辑。
注意事项
- 转换失败的处理:上面的适配器中我返回了默认值
0,你可以根据业务需求改成抛出异常,或者返回其他默认值(比如-1表示无效)。 - 空值处理:如果JSON字段可能为null,记得在适配器中处理
JsonToken.NULL的情况,避免空指针异常。
内容的提问来源于stack exchange,提问作者neelkanth_vyas
相关产品推荐
相关产品推荐

