【优化】SWAGGER: 修复swagger文档A属性引用B属性时 A属性中定义B字段上的 @Schema 注解不生效问题

This commit is contained in:
jerrywei 2024-09-11 23:35:26 +08:00
parent 000018826a
commit 16328e64c8
2 changed files with 80 additions and 19 deletions

View File

@ -15,6 +15,7 @@ import org.springdoc.core.*;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer; import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer; import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.providers.JavadocProvider; import org.springdoc.core.providers.JavadocProvider;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -105,8 +106,8 @@ public class YudaoSwaggerAutoConfiguration {
* 修复swagger文档A属性引用B属性时 A属性中定义B字段上的 @Schema 注解不生效问题 * 修复swagger文档A属性引用B属性时 A属性中定义B字段上的 @Schema 注解不生效问题
*/ */
@Bean @Bean
public SchemaPropertyFixModelConverter schemaPropertyFixModelConverter(){ public SchemaPropertyFixModelConverter schemaPropertyFixModelConverter(ObjectMapperProvider springDocObjectMapper){
return new SchemaPropertyFixModelConverter(); return new SchemaPropertyFixModelConverter(springDocObjectMapper);
} }
// ========== 分组 OpenAPI 配置 ========== // ========== 分组 OpenAPI 配置 ==========

View File

@ -1,16 +1,22 @@
package cn.iocoder.yudao.framework.swagger.core.converter; package cn.iocoder.yudao.framework.swagger.core.converter;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverterContext; import io.swagger.v3.core.converter.ModelConverterContext;
import io.swagger.v3.core.util.AnnotationsUtils;
import io.swagger.v3.core.util.RefUtils; import io.swagger.v3.core.util.RefUtils;
import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.providers.ObjectMapperProvider;
import java.util.Collection; import java.lang.annotation.Annotation;
import java.util.Iterator; import java.util.*;
import java.util.Map;
import java.util.Optional;
/** /**
* <p> * <p>
@ -24,13 +30,18 @@ import java.util.Optional;
*/ */
public class SchemaPropertyFixModelConverter implements ModelConverter { public class SchemaPropertyFixModelConverter implements ModelConverter {
/**
* The Spring doc object mapper.
*/
private final ObjectMapperProvider springDocObjectMapper;
/** /**
* Instantiates a new Polymorphic model converter. * Instantiates a new Polymorphic model converter.
* *
*/ */
public SchemaPropertyFixModelConverter() { public SchemaPropertyFixModelConverter(ObjectMapperProvider springDocObjectMapper) {
this.springDocObjectMapper = springDocObjectMapper;
} }
@Override @Override
@ -51,7 +62,7 @@ public class SchemaPropertyFixModelConverter implements ModelConverter {
* @param schemas the schemas * @param schemas the schemas
* @return the schema * @return the schema
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("all")
private Schema supplementarySchema(AnnotatedType type, Schema schema, Collection<Schema> schemas) { private Schema supplementarySchema(AnnotatedType type, Schema schema, Collection<Schema> schemas) {
// 拿到真实的类型定义 // 拿到真实的类型定义
Optional<Schema> schemaDefine = schemas.stream() Optional<Schema> schemaDefine = schemas.stream()
@ -67,6 +78,56 @@ public class SchemaPropertyFixModelConverter implements ModelConverter {
return schema; return schema;
} }
// 获取类型
ObjectMapper _mapper = springDocObjectMapper.jsonMapper();
final JavaType javaType;
if (type.getType() instanceof JavaType) {
javaType = (JavaType) type.getType();
} else {
javaType = _mapper.constructType(type.getType());
}
// 解析类属性描述
final BeanDescription beanDesc;
{
BeanDescription recurBeanDesc = _mapper.getSerializationConfig().introspect(javaType);
HashSet<String> visited = new HashSet<>();
JsonSerialize jsonSerialize = recurBeanDesc.getClassAnnotations().get(JsonSerialize.class);
while (jsonSerialize != null && !Void.class.equals(jsonSerialize.as())) {
String asName = jsonSerialize.as().getName();
if (visited.contains(asName)) break;
visited.add(asName);
recurBeanDesc = _mapper.getSerializationConfig().introspect(
_mapper.constructType(jsonSerialize.as())
);
jsonSerialize = recurBeanDesc.getClassAnnotations().get(JsonSerialize.class);
}
beanDesc = recurBeanDesc;
}
// 解析属性上的注解
List<BeanPropertyDefinition> propertiesDefine = beanDesc.findProperties();
Map<String, io.swagger.v3.oas.annotations.media.Schema> defineMap = new HashMap<>();
for (BeanPropertyDefinition propDef : propertiesDefine) {
List<Annotation> annotationList = new ArrayList<>();
for (Annotation a : propDef.getPrimaryMember().annotations()) {
annotationList.add(a);
}
Annotation[] annotations = annotationList.toArray(new Annotation[annotationList.size()]);
io.swagger.v3.oas.annotations.media.Schema ctxSchema = AnnotationsUtils.getSchemaAnnotation(annotations);
String propSchemaName = propDef.getName();
if (AnnotationsUtils.hasSchemaAnnotation(ctxSchema)) {
if (!StringUtils.isBlank(ctxSchema.name())) {
propSchemaName = ctxSchema.name();
}
}
defineMap.put(propSchemaName, ctxSchema);
}
// 重新补充属性描述
for (Object propertie : properties.values()) { for (Object propertie : properties.values()) {
if (propertie instanceof Schema) { if (propertie instanceof Schema) {
// 拿到属性的真实定义 // 拿到属性的真实定义
@ -75,17 +136,16 @@ public class SchemaPropertyFixModelConverter implements ModelConverter {
String propertieRef = propertieSchema.get$ref(); String propertieRef = propertieSchema.get$ref();
// 如果是引用类型, 则将真实定义的属性, 赋值到引用定义中 // 如果是引用类型, 则将真实定义的属性, 赋值到引用定义中
if (propertieRef != null) { if (propertieRef != null) {
schemas.stream() io.swagger.v3.oas.annotations.media.Schema propertieSchemaDefine = defineMap.get(propertieSchema.getName());
.filter(s -> propertieRef.equals(RefUtils.constructRef(s.getName())))
.findAny() if (AnnotationsUtils.hasSchemaAnnotation(propertieSchemaDefine)) {
.ifPresent(propertieSchemaDefine -> { if (!StrUtil.isBlank(propertieSchemaDefine.title())) {
if (StrUtil.isEmpty(propertieSchema.getTitle())) { propertieSchema.setTitle(propertieSchemaDefine.title());
propertieSchema.setTitle(propertieSchemaDefine.getTitle()); }
if (!StrUtil.isBlank(propertieSchemaDefine.description())) {
propertieSchema.setDescription(propertieSchemaDefine.description());
} }
if (StrUtil.isEmpty(propertieSchema.getDescription())) {
propertieSchema.setDescription(propertieSchemaDefine.getDescription());
} }
});
} }
} }