OpenAPI3生成Swagger文档时相同定义枚举展示不一致问题咨询
差异出现原因
- OpenAPI 3 文档生成框架默认会对被多处引用的类型自动抽取为公共Schema组件,生成
$ref引用,仅被单次引用的类型则会直接内联展示结构。Enum1仅在当前Request对象中被引用,因此直接内联展示枚举值;Enum2被至少两个不同的Schema/接口引用,因此被抽取为独立的公共组件。 - 你使用的enumeratum类型Scala枚举对应的Swagger序列化适配存在缺陷,抽取为公共组件时没有自动将枚举值写入组件Schema定义,导致生成的
Enum2组件仅标注为object类型,缺少枚举值列表。
解决方案
方案1:强制字段内联枚举值(最直接)
在field2的@Schema注解中显式指定类型为字符串,同时声明允许的枚举值,即可避免生成$ref引用,效果和Enum1完全一致:
@Schema( description = "Enum2 description", implementation = classOf[String], allowableValues = Array("Value3", "Value4") ) field2: Enum2
不想硬编码枚举值可以直接调用enumeratum的values方法:
allowableValues = Enum2.values.map(_.entryName).toArray
方案2:修复公共组件的枚举定义
如果希望保留$ref引用结构,只需要在Enum2的父特质上添加@Schema注解,显式声明类型和枚举值即可:
@Schema( description = "Enum2 description", `type` = "string", allowableValues = Array("Value3", "Value4") ) sealed trait Enum2 extends EnumEntry object Enum2 extends Enum[Enum2] { case object Value3 extends Enum2 case object Value4 extends Enum2 }
修改后生成的公共Schema组件就会包含正确的枚举值列表。
方案3:全局配置禁用枚举抽取
可以通过自定义OpenAPI Schema解析规则,全局禁止枚举类型被抽取为公共组件,所有枚举都直接内联展示。以SpringDoc框架为例,注册自定义的Schema转换器即可:
import io.swagger.v3.core.converter._ import io.swagger.v3.oas.models.media.StringSchema class EnumSchemaConverter extends ModelConverter { override def resolve(`type`: AnnotatedType, context: ModelConverterContext, chain: java.util.Iterator[ModelConverter]): Schema[_] = { if (classOf[EnumEntry].isAssignableFrom(`type`.getRawClass)) { val enumClazz = `type`.getRawClass.asInstanceOf[Class[_ <: EnumEntry]] val enumValues = Class.forName(enumClazz.getName + "$").getField("MODULE$").get(null) .asInstanceOf[Enum[_ <: EnumEntry]].values.map(_.entryName) new StringSchema()._enum(enumValues.toList.asJava) } else { if (chain.hasNext) chain.next().resolve(`type`, context, chain) else null } } }
注册后所有enumeratum枚举都会直接生成内联的字符串枚举结构,不会再生成$ref引用。
*注意:请确保项目已经引入了enumeratum-swagger依赖,否则默认的Swagger序列化器无法正确识别enumeratum枚举的结构,也会出现枚举值丢失的问题。
内容的提问来源于stack exchange,提问作者K D
相关产品推荐
相关产品推荐

