Spring Boot 3 WebFlux中移除输入对象的HATEOAS Links属性
问题分析
开启hateoas=true后,OpenAPI Generator会让所有生成的模型继承RepresentationModel,导致所有模型(包括作为请求体的输入模型)都带有links属性。你尝试的disallowAdditionalPropertiesIfNotPresent和@JsonInclude(NON_NULL)无效的原因:
disallowAdditionalPropertiesIfNotPresent仅控制是否允许JSON中的额外属性,不影响模型继承来的links字段links属性默认是空集合而非null,NON_NULL不会忽略空集合,且即使设置NON_EMPTY,第三方API可能仍不接受该字段
以下是无需新增对象映射的解决方案:
方案1:用Jackson Mixin忽略输入模型的Links属性
通过Jackson Mixin可以在不修改生成代码的前提下,指定序列化/反序列化时忽略输入模型的links属性:
步骤1:创建Mixin类
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.springframework.hateoas.RepresentationModel; // 定义Mixin,忽略links属性 @JsonIgnoreProperties({"links"}) public abstract class InputModelMixin extends RepresentationModel<InputModelMixin> { }
步骤2:在WebFlux配置中注册Mixin
将Mixin绑定到你的输入模型(比如Card),并注入到WebFlux的JSON编解码器中:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; import com.fasterxml.jackson.databind.ObjectMapper; import com.telr.tokenization.core.entities.Card; @Configuration public class WebFluxJacksonConfig { @Bean public Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper objectMapper) { // 给Card模型绑定Mixin,忽略links objectMapper.addMixIn(Card.class, InputModelMixin.class); // 如果有多个输入模型,重复addMixIn即可 return new Jackson2JsonEncoder(objectMapper); } @Bean public Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper objectMapper) { objectMapper.addMixIn(Card.class, InputModelMixin.class); return new Jackson2JsonDecoder(objectMapper); } }
这样当Card作为请求体序列化时,links属性会被自动忽略,不会传给第三方API。
方案2:自定义OpenAPI Generator模板,让输入模型不继承RepresentationModel
通过修改Generator的模板,让指定的输入模型不继承RepresentationModel,从根源上避免生成links属性:
步骤1:复制并修改模板
- 复制OpenAPI Generator的Spring模板中的
model.mustache到你的项目目录src/main/resources/openapi-templates - 修改模板中类继承的部分,加入对输入模型的判断:
{{#hateoas}} {{#vendorExtensions.x-is-input-model}} public class {{classname}} {{#parent}}implements {{parent}}{{/parent}} { {{/vendorExtensions.x-is-input-model}} {{^vendorExtensions.x-is-input-model}} public class {{classname}} extends RepresentationModel<{{classname}}> {{#parent}}implements {{parent}}{{/parent}} { {{/vendorExtensions.x-is-input-model}} {{/hateoas}} {{^hateoas}} public class {{classname}} {{#parent}}implements {{parent}}{{/parent}} { {{/hateoas}}
步骤2:在Swagger YAML中标记输入模型
给输入模型(比如Card)添加自定义扩展x-is-input-model: true:
components: schemas: Card: type: object x-is-input-model: true # 标记为输入模型,不生成links required: - number - expirationMonth - expirationYear properties: number: type: string expirationMonth: type: string expirationYear: type: string securityCode: type: string
步骤3:在插件配置中指定模板目录
修改openapi-generator-maven-plugin的配置,添加模板目录:
<configuration> <!-- 原有配置 --> <templateDirectory>${project.basedir}/src/main/resources/openapi-templates</templateDirectory> </configuration>
重新构建后,标记为x-is-input-model: true的模型将不会继承RepresentationModel,也就不会有links属性。
方案3:全局配置Jackson忽略RepresentationModel的links属性(可选)
如果所有输入模型都需要忽略links,可以直接给RepresentationModel添加Mixin,全局忽略该属性:
@JsonIgnoreProperties({"links"}) public abstract class RepresentationModelMixin extends RepresentationModel<RepresentationModelMixin> { }
然后在配置中绑定:
objectMapper.addMixIn(RepresentationModel.class, RepresentationModelMixin.class);
注意:此方法会让所有模型的links都被忽略,仅适合不需要在输出模型中返回links的场景,如果你需要输出模型保留links,请用方案1或2。
内容的提问来源于stack exchange,提问作者cyril

