ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

springdoc-openapi的救星:spring-addons-starter-openapi如何修复枚举值的OpenAPI规范生成

springdoc-openapi的救星:spring-addons-starter-openapi如何修复枚举值的OpenAPI规范生成 springdoc-openapi的救星spring-addons-starter-openapi如何修复枚举值的OpenAPI规范生成【免费下载链接】spring-addonsAdditional Spring Boot auto-configuration for OAuth2 / OpenID REST项目地址: https://gitcode.com/gh_mirrors/sp/spring-addons如果你的 Spring Boot 接口中使用了自定义toString()或JsonValue的枚举那么 springdoc-openapi 生成的枚举值 OpenAPI 规范很可能与真实接口行为不一致。spring-addons-starter-openapi是开源项目 spring-addons 中专门修复这一问题的组件它通过真实调用 Spring 的序列化机制让枚举值的 OpenAPI 规范生成变得准确、可靠是 springdoc-openapi 用户的必备救星。本文将深入剖析这个 bug 的成因并带你理解它的修复原理与使用方式。一个让人抓狂的 bug文档里的枚举值和接口实际接收的对不上 很多团队都有过这样的经历接口文档Swagger UI里明明写着枚举只能传A、B可当你真的传A时后端却报了参数转换错误或者文档提示name a但真实请求却需要传A。这个经典问题在 springdoc-openapi 社区中被广泛讨论issue #2494根源在于springdoc 默认按枚举的name()即枚举常量名生成枚举值列表而你的接口实际序列化时可能用的是toString()或JsonValue指定的值。两者一旦不一致生成的 OpenAPI 规范就成了错题集。比如下面这个枚举自定义了toString()返回中文标签public enum Status { PENDING(待处理), DONE(已完成); private final String label; // 构造器、toString() 返回 label... }springdoc 会生成enum: [PENDING, DONE]但 Jackson 实际序列化时配合JsonValue返回的却是待处理、已完成。文档与真实行为南辕北辙前端照着文档对接必然踩坑。为什么 springdoc-openapi 会生成错误的枚举值要理解这个 bug得先明白枚举序列化的两套体系JSON 序列化RequestBody/ResponseBody场景走 Spring 的HttpMessageConverter通常是 Jackson此时JsonValue、自定义toString()都会影响最终输出的字符串参数绑定RequestParam/PathVariable/RequestHeader等场景走FormattingConversionService默认使用Enum.valueOf(name)反序列化与 JSON 序列化并不是双射关系。springdoc-openapi 的默认ModelConverter并不关心这两套体系直接一刀切地输出name()于是当枚举存在JsonValue或自定义toString()时生成的枚举值 OpenAPI 规范就与真实接口脱节了。spring-addons-starter-openapi枚举值 OpenAPI 规范生成的救星 spring-addons 是一套为 Spring Boot 提供 OAuth2 / OpenID Connect 与 REST 能力增强的开源组件库其生态以 OIDC 授权码流程为根基如下所示。其中的spring-addons-starter-openapi模块正是为解决上述枚举值 OpenAPI 规范生成问题而生的它的核心思路非常朴素却极其有效不靠猜测让真正的序列化器说出每个枚举常量最终会被序列化成什么字符串再把它们写进 OpenAPI 规范。核心原理让真正的序列化器说话而不是靠猜 ️spring-addons-starter-openapi以 SwaggerModelConverter的形式切入 springdoc-openapi 的 schema 构建流程针对枚举类型分两条路径提取真实可用的值场景一RequestBody与ResponseBody中的枚举当枚举作为请求体或响应体的一部分时它调用容器中注册的HttpMessageConverter对每个枚举常量执行一次真实的写入write操作——借助内部的MockHttpOutputMessage捕获序列化输出再剥掉 Jackson 加上的双引号得到最终的字符串值。这意味着无论你是用JsonValue、自定义toString()还是全局序列化配置生成的枚举值都与实际 JSON 完全一致。场景二RequestParam、PathVariable等参数绑定中的枚举对于作为方法参数的枚举它改用FormattingConversionService尝试把每个枚举常量转成字符串如果找不到转换器则回退到toString()最后才考虑name()。更聪明的是它还会做一次反向验证把序列化出的值再反序列化回枚举只有全部成功才认定这组值是可信的。额外保障多转换器一致性校验 ⚠️如果同一个枚举被多个HttpMessageConverter支持且它们给出的可能值集合不一致starter 会直接抛出异常提醒开发者统一枚举的序列化策略——与其生成一份自相矛盾的文档不如在构建期就暴露问题。Servlet 与 WebFlux 双栈支持不同的应用架构使用不同的消息转换体系因此该模块针对两种栈分别提供了转换器实现应用类型转换器实现序列化通道Spring MVCServletSpringServletEnumModelConverterHttpMessageConverterSpring WebFluxReactiveSpringReactiveEnumModelConverterHttpMessageWriter自动配置类会根据ConditionalOnWebApplication自动选择合适的实现你无需写任何配置代码。三步上手把枚举值的 OpenAPI 规范生成交给它 引入依赖在pom.xml中加入spring-addons-starter-openapi依赖与springdoc-openapi-starter-webmvc-api或springdoc-openapi-starter-webflux-api配合使用可选依赖声明见 pom.xml启动应用SpringAddonsOpenapiAutoConfiguration会自动注册枚举 ModelConverter参见 SpringAddonsOpenapiAutoConfiguration.java验证效果打开/v3/api-docs或 Swagger UI确认枚举 schema 中的enum列表已变为真实的序列化值。想要阅读源码关键实现都在这几个文件里值得细细品味枚举值提取接口EnumPossibleValuesExtractor.javaServlet 转换器实现SpringServletEnumModelConverter.javaWebFlux 转换器实现SpringReactiveEnumModelConverter.java模拟输出消息用于捕获真实序列化结果MockHttpOutputMessage.java用官方复现工程验证修复效果 ✅spring-addons 仓库中内置了针对 issue #2494 的复现与验证工程分别覆盖 Servlet 与 Reactive 两种栈samples/springdoc-openapi-2494-servletsamples/springdoc-openapi-2494-reactive工程中定义了三种典型枚举默认name()序列化、JsonValue强制toString()序列化、带双向转换器的枚举并预置了生成好的 openapi.json 供对比。你也可以git clone https://gitcode.com/gh_mirrors/sp/spring-addons后本地运行直观对比启用本 starter 前后枚举值 OpenAPI 规范生成结果的差异。总结springdoc-openapi 的枚举文档 bug 困扰过无数开发者而spring-addons-starter-openapi用一个巧妙的设计给出了优雅的解法以真实序列化结果为准替代默认的name()猜测并覆盖RequestBody、RequestParam等全部常见场景还贴心地区分了 Servlet 与 WebFlux 双栈。如果你的项目正被枚举值的 OpenAPI 规范生成问题困扰不妨立即试试这个组件——让文档与接口行为始终如一从枚举开始。【免费下载链接】spring-addonsAdditional Spring Boot auto-configuration for OAuth2 / OpenID REST项目地址: https://gitcode.com/gh_mirrors/sp/spring-addons创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表