Tapir中密封特质ErrorResponse的Schema定义问题:Swagger显示对象层级而非具体子类型
Tapir中密封特质ErrorResponse的Schema定义问题:Swagger显示对象层级而非具体子类型
嗨,我之前也碰到过一模一样的问题!这本质是因为Tapir默认派生的密封特质Schema没有配置鉴别器(discriminator),导致Swagger没法识别子类型的具体名称,只能用默认的#0、#1来标记层级。咱们可以通过给Schema添加鉴别器配置来解决这个问题,具体操作如下:
核心思路
给密封特质的每个子类型添加一个用于区分的固定字段(比如type),然后在根特质的Schema中指定这个字段作为鉴别器,让Swagger能关联到具体的子类型名称。
修改后的代码实现
// 先给ErrorResponse特质添加type字段定义 sealed trait ErrorResponse { def `type`: String } object ErrorResponse { // 每个子类型实现type字段,固定为自身的类型名称 final case class NotFound(id: String) extends ErrorResponse { override val `type`: String = "NotFound" } final case class UnknownError(error: String) extends ErrorResponse { override val `type`: String = "UnknownError" } // 为子类型的Schema固定type字段的值,避免被当作可修改参数 implicit val notFoundSchema: Schema[NotFound] = Schema.derived .modify(_.`type`)(_.withFixedValue("NotFound")) implicit val unknownErrorSchema: Schema[UnknownError] = Schema.derived .modify(_.`type`)(_.withFixedValue("UnknownError")) // 为根特质Schema指定鉴别器字段为"type" implicit val errorResponseSchema: Schema[ErrorResponse] = Schema.derived .withDiscriminator("type") }
为什么这样有效?
- 每个子类型的
type字段有唯一固定值,Swagger可以通过这个字段区分不同错误类型; withDiscriminator("type")告诉Tapir在生成OpenAPI文档时,用type字段作为鉴别器,把每个子类型的名称对应到这个字段的值上;withFixedValue确保这个字段在Swagger里是只读的固定值,不会被当作可输入的参数。
额外小提示
如果你不想在case class里显式添加type字段,也可以通过Schema的addField方法添加一个虚拟字段,但显式添加的方式更直观,也能让API的消费者更清晰地理解错误类型。
你的依赖版本(1.9.6)完全支持这个配置,修改后重启服务,再看Swagger文档就能看到NotFound和UnknownError的具体子类型了!
备注:内容来源于stack exchange,提问作者M.G.
相关产品推荐
相关产品推荐

