You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Doc中全局自定义Either响应类的处理逻辑?

解决方案

要实现Spring Doc全局自动解析Arrow-Kt Either<L, R>类型,只展示Right分支作为成功响应,无需逐个添加@ApiResponse,可以通过扩展Spring Doc的自定义组件实现,核心思路是拦截响应类型解析,将Either的泛型参数Right分支提取为实际响应类型。

1. 自定义OperationCustomizer处理响应类型

创建实现OperationCustomizer的类,遍历接口的响应定义,识别Either类型并替换为其Right分支的泛型类型:

import arrow.core.Either
import io.swagger.v3.core.converter.ModelConverters
import io.swagger.v3.oas.models.Operation
import io.swagger.v3.oas.models.media.MediaType
import io.swagger.v3.oas.models.media.Schema
import org.springdoc.core.customizers.OperationCustomizer
import org.springdoc.core.providers.RequestBuilder
import org.springframework.stereotype.Component
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

@Component
class EitherOperationCustomizer(
    private val requestBuilder: RequestBuilder,
    private val modelConverters: ModelConverters
) : OperationCustomizer {

    override fun customize(operation: Operation, handlerMethod: org.springframework.web.method.HandlerMethod): Operation {
        // 遍历所有响应,处理成功响应(默认200)
        operation.responses.values.forEach { apiResponse ->
            apiResponse.content?.values?.forEach { mediaType ->
                val schema = mediaType.schema ?: return@forEach
                // 检查当前schema是否对应Either类型
                if (isEitherType(schema.implementation)) {
                    val rightType = extractRightType(schema.implementation as ParameterizedType)
                    // 生成Right类型的Schema
                    val rightSchema = modelConverters.readAll(rightType).values.firstOrNull()
                    rightSchema?.let {
                        mediaType.schema = it
                    }
                }
            }
        }
        return operation
    }

    private fun isEitherType(type: Class<*>?): Boolean {
        return type != null && Either::class.java.isAssignableFrom(type)
    }

    private fun extractRightType(parameterizedType: ParameterizedType): Type {
        // Either<L, R>的第二个泛型参数是Right分支
        return parameterizedType.actualTypeArguments[1]
    }
}

2. 自定义SchemaCustomizer(可选,优化全局Schema定义)

如果需要确保全局Schema中不生成Either类型的冗余定义,可以添加SchemaCustomizer过滤掉Either的Schema:

import arrow.core.Either
import io.swagger.v3.oas.models.media.Schema
import org.springdoc.core.customizers.SchemaCustomizer
import org.springframework.stereotype.Component

@Component
class EitherSchemaCustomizer : SchemaCustomizer {
    override fun customize(schema: Schema<*>?, type: Class<*>?, name: String?, context: MutableMap<String, Any>?): Schema<*>? {
        // 如果当前类型是Either,返回null不生成对应的Schema
        return if (Either::class.java.isAssignableFrom(type)) null else schema
    }
}

3. 验证效果

启动Spring应用后,访问Swagger UI(默认路径/swagger-ui.html),查看返回Either类型的接口:

  • 成功响应(200)的模型会自动展示为Either的Right分支类型
  • 无需在每个控制器方法上添加@ApiResponse指定响应模型

关键说明

  • 上述代码通过反射提取Either<L, R>的第二个泛型参数作为响应类型,完全适配Arrow-Kt的Either结构
  • OperationCustomizer会拦截每个接口的OpenAPI定义,动态替换响应Schema
  • 如果需要在Swagger中展示Left分支对应的错误响应,可以在customize方法中额外处理4xx/5xx响应,将Left分支类型作为错误响应模型

内容的提问来源于stack exchange,提问作者craigmiller160

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:30:59