Gson处理继承关系的核心是显式携带类型信息,通过RuntimeTypeAdapterFactory注册子类映射并依赖JSON中的type字段实现多态反序列化。

用 Gson 处理带继承关系的复杂对象,核心不是“绕开类型”,而是“显式携带类型信息”。默认 Gson 无法区分父类引用背后的实际子类,反序列化时会构造出父类实例,字段丢失、方法失效。关键在 RuntimeTypeAdapterFactory —— 它让 JSON 自带 type 字段,Gson 读取时按需实例化具体子类。
注册 RuntimeTypeAdapterFactory 明确类型映射
这是多态序列化的起点。不能只传父类类型,必须告诉 Gson “哪些子类合法”以及 “怎么识别它们”:
- 创建工厂时指定基类,如
RuntimeTypeAdapterFactory.of(Animal.class) - 逐个注册子类:
.registerSubtype(Dog.class, "dog")(第二个参数是 JSON 中的 type 标识,默认用类名小写) - 注册到 GsonBuilder:
new GsonBuilder().registerTypeAdapterFactory(rta).create() - type 字段默认插入在 JSON 顶层,值为注册时指定的字符串;也可用
setIdentifier改为嵌套字段或自定义键名
确保 JSON 输入含 type 字段且值匹配
反序列化依赖 type 字段值与注册标识严格一致。常见问题不是代码错,而是数据没对上:
- 手动构造 JSON 时,必须包含
"type": "dog"(或你注册的其他标识) - 若后端返回的 type 是大写或带前缀(如
"type": "ANIMAL_DOG"),注册时就得写成.registerSubtype(Dog.class, "ANIMAL_DOG") - type 字段位置要和工厂配置一致:默认在根对象一级,不支持放在嵌套层里(如
{"pet": {"type":"dog", ...}}需额外适配)
处理嵌套多态与泛型集合
当多态对象出现在 List 或 Map 中,或作为其他对象的字段,规则不变,但需注意泛型擦除:
立即学习“Java免费学习笔记(深入)”;
- 单个对象反序列化:
gson.fromJson(json, Animal.class)即可,工厂自动识别 type 并实例化 Dog/Cat - 列表场景必须用 TypeToken:
gson.fromJson(json, new TypeToken<List<Animal>>() {}.getType()) - 嵌套字段(如
class Zoo { List<Animal> animals; })无需额外操作,只要 Zoo 类字段类型是 Animal,工厂仍生效 - 避免把 TypeToken 写成静态常量——匿名内部类在某些容器环境可能触发序列化异常
配合 @SerializedName 和字段策略保持兼容
多态对象常与其他规范共存,比如 REST API 要求下划线命名,或字段别名:
- 在 Animal 及其子类中,用
@SerializedName("pet_type")修饰 type 字段(如果后端字段名不是默认的 "type") - 全局命名策略(如
LOWER_CASE_WITH_UNDERSCORES)不影响 type 字段,它由 RuntimeTypeAdapterFactory 独立控制 - 子类特有字段无需额外注解,只要在子类中声明,序列化时自动包含;反序列化时也仅该子类能解析这些字段


















