如何在Java子类中重写父类的Swagger @Schema注解?
嘿,我来给你说说怎么在子类里替换父类的Swagger @Schema注解内容哈~
首先得明确:Java的字段没法直接「重写」,只能隐藏,而且Swagger的@Schema注解本身也没有专门的重写属性,但我们有几种靠谱的办法实现类似效果:
方法一:子类重新定义字段+@JsonProperty
这是最直接的方式,在子类里重新定义和父类同名的字段,加上你想要的新@Schema注解,再用@JsonProperty保证JSON序列化/反序列化不冲突。
先看你的父类代码:
public abstract class Measurement { @Schema(description = "The value", example = "1") public Double amount; @Schema(description = "The unit", example = "m") public String unit; // 其他代码... }
子类Weight这么写:
public class Weight extends Measurement { @Schema(description = "体重数值", example = "75") @JsonProperty public Double amount; @Schema(description = "体重单位", example = "kg") @JsonProperty public String unit; // 其他代码... }
这样Swagger文档里就会显示子类的注解内容了,@JsonProperty是告诉JSON处理工具(比如Jackson),这个字段对应JSON里的目标key,避免子类重定义字段导致序列化问题。不过要注意,这种方式会让子类自己持有amount和unit字段,父类的同名字段会被隐藏,业务逻辑上要确认没问题哦。
方法二:重写父类的getter方法(更规范)
如果父类把@Schema注解加在getter方法上(不是直接加字段),那你可以在子类里重写这些getter,然后在重写的方法上贴新的@Schema注解,这更符合Java继承规范。
调整父类为getter注解的写法:
public abstract class Measurement { private Double amount; private String unit; @Schema(description = "The value", example = "1") public Double getAmount() { return amount; } public void setAmount(Double amount) { this.amount = amount; } @Schema(description = "The unit", example = "m") public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } }
子类Weight重写getter:
public class Weight extends Measurement { @Override @Schema(description = "体重数值", example = "75") public Double getAmount() { return super.getAmount(); } @Override @Schema(description = "体重单位", example = "kg") public String getUnit() { return super.getUnit(); } }
这种方式没有字段隐藏的问题,完全是标准的方法重写,Swagger会优先识别子类重写方法上的注解,完美覆盖父类内容,非常推荐这种写法~
方法三:Swagger 3专属类上注解
如果你的项目用的是Swagger 3(比如springdoc-openapi环境),还可以直接在子类的类上用@Schema的properties属性指定字段的注解,不用重定义字段或方法:
@Schema(properties = { @SchemaProperty(name = "amount", description = "体重数值", example = "75"), @SchemaProperty(name = "unit", description = "体重单位", example = "kg") }) public class Weight extends Measurement { // 不需要额外写字段或方法 }
不过要注意,这种方式只有Swagger 3的部分实现支持,老版本Swagger(比如Swagger 2)用不了哦。
总结一下:父类字段是public/protected时,方法一兼容性最好;父类用getter注解时,方法二更规范;Swagger 3环境可以试试方法三~
备注:内容来源于stack exchange,提问作者Essej

