如何在Java中实现JSON对象共享字段的无重复类定义?
解决方案:基于抽象父类的不可变实体设计
核心思路
通过抽象父类封装共享字段,子类继承父类并仅定义专属属性,结合Jackson的构造器注解实现无冗余的不可变类设计。由于反序列化时已明确指定目标类型,无需使用@JsonTypeInfo。
代码实现
1. 抽象父类(封装共享字段)
定义抽象类Pet,包含所有实体共享的name和age字段,通过带参构造器初始化,并添加@JsonProperty注解完成JSON字段映射:
import com.fasterxml.jackson.annotation.JsonProperty; public abstract class Pet { private final String name; private final int age; protected Pet(@JsonProperty("name") String name, @JsonProperty("age") int age) { this.name = name; this.age = age; } // 不可变类仅提供只读访问方法 public String getName() { return name; } public int getAge() { return age; } }
2. 子类实现(仅定义专属属性)
每个子类继承Pet,仅声明自身专属的不可变字段,通过@JsonCreator标注构造器,确保Jackson能正确识别并完成反序列化:
Dog类示例
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class Dog extends Pet { private final String breed; @JsonCreator public Dog( @JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("breed") String breed ) { super(name, age); this.breed = breed; } public String getBreed() { return breed; } }
Cat类示例
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class Cat extends Pet { private final boolean hasClaws; @JsonCreator public Cat( @JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("hasClaws") boolean hasClaws ) { super(name, age); this.hasClaws = hasClaws; } public boolean isHasClaws() { return hasClaws; } }
Fish类示例
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class Fish extends Pet { private final String waterType; @JsonCreator public Fish( @JsonProperty("name") String name, @JsonProperty("age") int age, @JsonProperty("waterType") String waterType ) { super(name, age); this.waterType = waterType; } public String getWaterType() { return waterType; } }
方案优势说明
- 无冗余代码:共享字段和
@JsonProperty仅在父类定义一次,子类无需重复编写。 - 不可变性保证:所有字段均为
final,无setter方法,构造器初始化所有属性,符合不可变类设计规范。 - 无需类型注解:反序列化时明确指定目标类型(如
mapper.readValue(input, Dog.class)),Jackson会直接调用对应子类的@JsonCreator构造器,自动完成父类与子类字段的映射,完全不需要@JsonTypeInfo。
内容的提问来源于stack exchange,提问作者EarthTurtle
相关产品推荐
相关产品推荐

