Spring Boot Swagger如何自定义第三方starter中Wrapper泛型类的UI展示
实现方案
针对无法修改第三方Wrapper类源码的场景,可通过以下3种方案实现Swagger模型自定义,你可以根据项目中Wrapper的使用频次选择对应方案:
方案1:单接口注解覆盖(适合少量接口使用Wrapper的场景)
直接在控制器方法的SpringMVC @RequestBody参数上,叠加Swagger提供的@io.swagger.v3.oas.annotations.parameters.RequestBody注解,手动定义Wrapper的Schema结构,内部data字段指定为你的业务Request类即可自动继承@Schema配置:
@PostMapping("/your/api") public void yourApi( // Swagger自定义Schema注解 @io.swagger.v3.oas.annotations.parameters.RequestBody( content = @Content( schema = @Schema( description = "统一请求包装类", requiredProperties = {"requestId", "timestamp", "data"}, example = "{\"requestId\":\"xxx\",\"timestamp\":1690000000000,\"data\":{}}", properties = { @SchemaProperty(name = "requestId", type = "string", description = "请求唯一ID"), @SchemaProperty(name = "timestamp", type = "integer", format = "int64", description = "请求时间戳"), @SchemaProperty(name = "data", implementation = Request.class, description = "业务请求参数") } ) ) ) // 原有SpringMVC参数注解 @org.springframework.web.bind.annotation.RequestBody Wrapper<Request> requestBody) { // 业务逻辑 }
方案2:全局ModelConverter配置(适合大量接口使用Wrapper泛型的场景)
实现SpringDoc提供的ModelConverter接口,全局拦截Wrapper泛型的解析过程,动态嵌入泛型参数的Schema,一劳永逸处理所有Wrapper<T>类型:
- 自定义模型解析转换器
import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.LongSchema; import org.springframework.stereotype.Component; import java.lang.reflect.Type; import java.lang.reflect.ParameterizedType; import java.util.Iterator; @Component public class WrapperModelConverter implements ModelConverter { @Override public Schema resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) { // 匹配Wrapper泛型类型 if (type instanceof ParameterizedType parameterizedType && parameterizedType.getRawType() == Wrapper.class) { // 获取泛型实际参数(即业务Request类) Type bizType = parameterizedType.getActualTypeArguments()[0]; // 解析业务类的原生Schema(自动继承@Schema注解配置) Schema bizSchema = context.resolve(bizType); // 手动构造Wrapper的Schema结构 Schema wrapperSchema = new Schema<>(); wrapperSchema.setDescription("统一请求包装类"); wrapperSchema.addProperty("requestId", new StringSchema().description("请求唯一ID")); wrapperSchema.addProperty("timestamp", new LongSchema().description("请求时间戳")); wrapperSchema.addProperty("data", bizSchema.description("业务请求参数")); // 配置必填字段 wrapperSchema.addRequiredItem("requestId"); wrapperSchema.addRequiredItem("timestamp"); wrapperSchema.addRequiredItem("data"); return wrapperSchema; } // 非Wrapper类型走原有解析逻辑 return chain.next().resolve(type, context, chain); } }
- 注册转换器:SpringDoc 1.6+版本添加
@Component注解即可自动生效,旧版本可通过如下配置手动注册:
@Configuration public class SpringDocConfig { @Bean public ModelConverterWrapper wrapperModelConverter(WrapperModelConverter converter) { // 优先级设置为-1,优先于默认解析器执行 return new ModelConverterWrapper(converter, -1); } }
方案3:Jackson混合注解(适合Wrapper结构固定、无动态泛型处理需求的场景)
通过Jackson的Mixin功能给第三方Wrapper类动态添加@Schema注解,无需修改源码:
- 定义混合接口
@Schema(description = "统一请求包装类", requiredProperties = {"requestId", "timestamp", "data"}) public interface WrapperMixin<T> { @Schema(description = "请求唯一ID") String getRequestId(); @Schema(description = "请求时间戳") Long getTimestamp(); @Schema(description = "业务请求参数") T getData(); }
- 注册混合类到Jackson
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.addMixIn(Wrapper.class, WrapperMixin.class); return objectMapper; } }
内容的提问来源于stack exchange,提问作者tarmogoyf
相关产品推荐
相关产品推荐

