自定义Swagger(knif4j)枚举类型展示

适配swagger枚举类型的数据展示方式,不要只展示枚举字段的名称

在这里插入图片描述

@Component
public class ApiEnumPropertyBuilder implements ModelPropertyBuilderPlugin {

    /** Descriptions */
    private final DescriptionResolver descriptions;

    /** Model specifications */
    private final ModelSpecificationFactory modelSpecifications;


    /**
     * Api enum property reference builder
     *
     * @param descriptions        descriptions
     * @param modelSpecifications model specifications
     * @since 1.0.0
     */
    public ApiEnumPropertyBuilder(
            DescriptionResolver descriptions,
            ModelSpecificationFactory modelSpecifications) {
        this.descriptions = descriptions;
        this.modelSpecifications = modelSpecifications;
    }

    /**
     * 定义model的字段解析
     *
     * @param context context
     * @since 1.0.0
     */
    @Override
    public void apply(ModelPropertyContext context) {
        Optional<ApiEnumProperty> annotation = empty();

        Optional<BeanPropertyDefinition> definition = context.getBeanPropertyDefinition();
        if (!definition.isPresent()) {
            return;
        }
        if (context.getAnnotatedElement().isPresent()) {
            annotation =
                    annotation.map(Optional::of)
                            .orElse(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
        }
        annotation = annotation.map(Optional::of).orElse(findPropertyAnnotation(
                definition.get(),
                ApiEnumProperty.class));
        BeanPropertyDefinition propertyDefinition = definition.get();
        Class<?> type = propertyDefinition.getRawPrimaryType();
        if (annotation.isPresent()) {
            this.extractByAnnotation(context, annotation);
            return;
        }
        if (SerializeEnum.class.isAssignableFrom(type)) {
            this.extractByType(context, type);
        }
    }

    /**
     * Extract by type
     *
     * @param context context
     * @param type    type
     * @since 1.0.0
     */
    private void extractByType(ModelPropertyContext context, Class<?> type) {
        context.getSpecificationBuilder()
                .enumerationFacet(e -> e.allowedValues(toAllowableValues(type)));
        context.getBuilder()
                .allowableValues(toAllowableValues(type));
    }

    /**
     * Extracted
     *
     * @param context    context
     * @param annotation annotation
     * @since 1.0.0
     */
    private void extractByAnnotation(ModelPropertyContext context, Optional<ApiEnumProperty> annotation) {
        ModelSpecification modelSpecification =
                annotation.map(a -> {
                            if (a.enumClz() != Enum.class) {
                                return this.modelSpecifications
                                        .create(context.getOwner(), toType(context.getResolver()).apply(a));
                            }
                            return null;
                        })
                        .orElse(null);
        ApiEnumProperty enumPropertyReference = annotation.get();
        Class<? extends Enum> enumClz = enumPropertyReference.enumClz();
        context.getSpecificationBuilder()
                .description(annotation.map(toDescription(this.descriptions)).orElse(null))
                .isHidden(annotation.map(ApiEnumProperty::hidden).orElse(false))
                .type(modelSpecification)
                .position(annotation.map(ApiEnumProperty::position).orElse(0))
                .required(annotation.map(ApiEnumProperty::required).orElse(false))
                .example(annotation.map(toExample()).orElse(null))
                .enumerationFacet(e -> e.allowedValues(toAllowableValues(enumClz)));

        context.getBuilder()
                .allowableValues(toAllowableValues(enumClz))
                .required(annotation.map(ApiEnumProperty::required).orElse(false))
                .description(annotation.map(toDescription(this.descriptions)).orElse(null))
                .isHidden(annotation.map(ApiEnumProperty::hidden).orElse(false))
                .type(annotation.map(toType(context.getResolver())).orElse(null))
                .position(annotation.map(ApiEnumProperty::position).orElse(0))
                .example(annotation.map(toExample()).orElse(null));
    }

    /**
     * Supports
     *
     * @param documentationType documentation type
     * @return the boolean
     * @since 1.0.0
     */
    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }


    /**
     * Find api mode property annotation
     *
     * @param annotated annotated
     * @return the optional
     * @since 1.0.0
     */
    public static Optional<ApiEnumProperty> findApiModePropertyAnnotation(AnnotatedElement annotated) {
        Optional<ApiEnumProperty> annotation = empty();
        if (annotated instanceof Method) {
            annotation = ofNullable(AnnotationUtils.findAnnotation(((Method) annotated), ApiEnumProperty.class));
        }
        return annotation.map(Optional::of).orElse(ofNullable(AnnotationUtils.getAnnotation(annotated,
                ApiEnumProperty.class)));
    }

    /**
     * To type
     *
     * @param resolver resolver
     * @return the function
     * @since 1.0.0
     */
    public static Function<ApiEnumProperty, ResolvedType> toType(final TypeResolver resolver) {
        return annotation -> resolver.resolve(annotation.enumClz());
    }

    /**
     * To description
     *
     * @param descriptions descriptions
     * @return the function
     * @since 1.0.0
     */
    public static Function<ApiEnumProperty, String> toDescription(
            final DescriptionResolver descriptions) {
        return annotation -> {
            String description = "";
            if (!isEmpty(annotation.value())) {
                description = annotation.value();
            } else if (!isEmpty(annotation.notes())) {
                description = annotation.notes();
            }
            return descriptions.resolve(description);
        };
    }

    /**
     * To example
     *
     * @return the function
     * @since 1.0.0
     */
    public static Function<ApiEnumProperty, String> toExample() {
        return annotation -> {
            String example = "";
            if (!isEmpty(annotation.example())) {
                example = annotation.example();
            }
            return example;
        };
    }

    /**
     * To allowable values
     *
     * @param type type
     * @return the function
     * @since 1.0.0
     */
    @SuppressWarnings("all")
    public static AllowableValues toAllowableValues(Class<?> type) {
        List<String> list = new ArrayList<>();
        if (SerializeEnum.class.isAssignableFrom(type)) {
            Class<SerializeEnum<?>> serializeEnumClass = (Class<SerializeEnum<?>>) type;
            SerializeEnum<?>[] constants = serializeEnumClass.getEnumConstants();
            if (constants != null) {
                Stream.of(constants)
                        .forEach(item -> list.add(String.format("(%s,%s)", item.getValue(), item.getDesc())));
            }
        } else {
            Class<? extends Enum> enumClz = (Class<? extends Enum>) type;
            Enum[] enumConstants = enumClz.getEnumConstants();
            if (enumConstants != null) {
                Stream.of(enumConstants)
                        .forEach(item -> list.add(String.format("(%d,%s)", item.ordinal(), item.name())));
            }
        }
        AllowableListValues values = new AllowableListValues(Collections.unmodifiableList(list), "LIST");
        return values;
    }
}

自定义枚举属性的注解

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiEnumProperty {

    /**
     * Value
     *
     * @return the string
     * @since 1.0.0
     */
    String value();

    /**
     * Enum clz
     *
     * @return the class
     * @since 1.0.0
     */
    Class<? extends Enum> enumClz() default Enum.class;

    /**
     * Name
     *
     * @return the string
     * @since 1.0.0
     */
    String name() default "";

    /**
     * Access
     *
     * @return the string
     * @since 1.0.0
     */
    String access() default "";

    /**
     * Notes
     *
     * @return the string
     * @since 1.0.0
     */
    String notes() default "";


    /**
     * Required
     *
     * @return the boolean
     * @since 1.0.0
     */
    boolean required() default false;

    /**
     * Position
     *
     * @return the int
     * @since 1.0.0
     */
    int position() default 0;

    /**
     * Hidden
     *
     * @return the boolean
     * @since 1.0.0
     */
    boolean hidden() default false;

    /**
     * Example
     *
     * @return the string
     * @since 1.0.0
     */
    String example() default "";
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值