Swagger UI文档无法显示鉴别器type可选值的问题求助
问题描述
我希望在Swagger UI的API文档中,让Conversion和Analysis这两个可选值显示在响应Schema的type字段中。我的API返回TaskOutput类型对象,其中data字段是两种类型之一。目前Swagger UI里仅能看到type属性被标记为必填字符串类型,导致API使用者无法知晓type字段的具体取值选项——尽管实际响应的序列化格式是正确的,但文档信息不完整。
我的代码如下:
public class TaskOutput { private TaskDataOutput data; @JsonProperty("data") @Schema(name = "data", oneOf = { AnalysisTaskDataOutput.class, ConversionTaskDataOutput.class }) public TaskDataOutput getData() { return data; } } public class AnalysisTaskDataOutput implements TaskDataOutput { private Boolean cleanup; @Schema(name = "cleanup") @JsonProperty("cleanup") public Boolean getCleanup() { return cleanup; } } public class ConversionTaskDataOutput implements TaskDataOutput { private Boolean converted; @Schema(name = "converted") @JsonProperty("converted") public Boolean getConverted() { return converted; } } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = AnalysisTaskDataOutput.class, name = "Analysis"), @JsonSubTypes.Type(value = ConversionTaskDataOutput.class, name = "Conversion"), }) public interface TaskDataOutput { }
我尝试过创建包含Analysis和Conversion的枚举,并在接口中定义DataType getType()方法,但Swagger UI里还是不显示这些可选值。
解决方案
Swagger默认不会自动读取Jackson多态注解里的类型名称,需要通过以下两种方式让type字段的可选值显示在文档中:
方案1:在接口中显式定义带约束的type方法
修改TaskDataOutput接口,添加getType()方法并通过@Schema指定允许的取值,同时在实现类中返回对应类型名称:
import io.swagger.v3.oas.annotations.media.Schema; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true) @JsonSubTypes({ @JsonSubTypes.Type(value = AnalysisTaskDataOutput.class, name = "Analysis"), @JsonSubTypes.Type(value = ConversionTaskDataOutput.class, name = "Conversion"), }) public interface TaskDataOutput { @Schema(name = "type", allowableValues = {"Analysis", "Conversion"}, required = true) String getType(); }
实现类补充方法:
public class AnalysisTaskDataOutput implements TaskDataOutput { private Boolean cleanup; @Schema(name = "cleanup") @JsonProperty("cleanup") public Boolean getCleanup() { return cleanup; } @Override public String getType() { return "Analysis"; } } public class ConversionTaskDataOutput implements TaskDataOutput { private Boolean converted; @Schema(name = "converted") @JsonProperty("converted") public Boolean getConverted() { return converted; } @Override public String getType() { return "Conversion"; } }
方案2:自定义转换器自动解析Jackson多态注解
如果不想改动业务代码,可以通过自定义ModelConverter让Swagger自动读取@JsonSubTypes中的类型名称:
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.oas.models.media.Schema; import org.springframework.stereotype.Component; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @Component public class JacksonPolymorphismModelConverter implements ModelConverter { @Override public Schema resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) { Schema schema = chain.hasNext() ? chain.next().resolve(type, context, this) : null; if (schema == null || !(type instanceof Class)) { return schema; } Class<?> clazz = (Class<?>) type; JsonTypeInfo typeInfo = clazz.getAnnotation(JsonTypeInfo.class); if (typeInfo != null && typeInfo.use() == JsonTypeInfo.Id.NAME) { JsonSubTypes subTypes = clazz.getAnnotation(JsonSubTypes.class); if (subTypes != null && subTypes.value().length > 0) { List<String> allowableValues = List.of(subTypes.value()).stream() .map(JsonSubTypes.Type::name) .collect(Collectors.toList()); // 给type字段设置枚举值和描述 schema.getProperties().get(typeInfo.property()) .setEnum(allowableValues) .setDescription("任务类型:" + String.join("、", allowableValues)); } } return schema; } }
这个转换器会自动扫描带Jackson多态注解的接口,把@JsonSubTypes里的类型名称同步到Swagger的Schema中,无需修改业务类。
内容的提问来源于stack exchange,提问作者DArkO
相关产品推荐
相关产品推荐

