【问题标题】:Hide property in a subclass of a @ParameterObject with springdoc使用springdoc隐藏@ParameterObject子类中的属性
【发布时间】:2022-05-03 19:55:34
【问题描述】:

我们正在从 spring-fox 迁移到 springdoc。

有时我们需要隐藏@ParameterObjects 中使用的公共基类的属性。

使用 spring-fox (swagger2) 效果很好:

    public class BaseParameters {
        private String baseProperty; 
    }
    
    class CustomizedParameters extends BaseParameters {
        @Override
        @ApiParam(hidden = true)
        public String getBaseProperty() {
            return null;
        }
    }

baseProperty 未显示在 api-docs 中

但是对于 Springdoc,这不起作用:

@ParameterObject
public class BaseParameters {
    private String baseProperty; 
}

@ParameterObject    
class CustomizedParameters extends BaseParameters {
    @Override
    @Hidden
    public String getBaseProperty() {
        return null;
    }
}

我还尝试使用 @Parameter(hidden=true) 和 @JsonIgnore 隐藏 baseProperty,但该属性仍保留在规范中

我错过了什么? springdoc不支持这个吗?有什么解决办法吗?

【问题讨论】:

    标签: openapi springdoc


    【解决方案1】:

    我为这个问题写了一个解决方法。但是注解必须放在类的属性中。

    问题出在MethodParameterPojoExtractor没有考虑子类属性的注解(Hidden, JsonIgnore ...)。

    下面使用反射的代码强制在生成的方法参数中使用隐藏注释进行填充。

    OBS:如果子类的层次大1,可能是抛出错误。因为我做的很匆忙。

    @Bean
    GenericParameterService parameterBuilder(PropertyResolverUtils propertyResolverUtils, Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider) {
        return new GenericParameterService(propertyResolverUtils, delegatingMethodParameterCustomizer(),
                    optionalWebConversionServiceProvider);
    }
    
    private Optional<DelegatingMethodParameterCustomizer> delegatingMethodParameterCustomizer() { // NOSONAR
        return Optional.of((originalMethodParam, methodParam) -> {
            if (originalMethodParam.hasParameterAnnotations()
                && originalMethodParam.hasParameterAnnotation(ParameterObject.class)
            ) {
                try {
                    if (isParameterIgnore(originalMethodParam, methodParam)) {
                        Field field = FieldUtils.getDeclaredField(DelegatingMethodParameter.class, "additionalParameterAnnotations", true);
                        try {
                            field.set(methodParam, new Annotation[] {new Hidden() { // NOSONAR
                                @Override
                                public Class<? extends Annotation> annotationType() {
                                    return Hidden.class;
                                }}
                            });
                        } catch (IllegalArgumentException|IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (NoSuchFieldException | SecurityException e) {
                    e.printStackTrace();
                }
            }
        });
    }
        
    private boolean isParameterIgnore(MethodParameter originalMethodParam, MethodParameter methodParam) throws NoSuchFieldException, SecurityException {
        String parameterName = Objects.requireNonNullElse(methodParam.getParameterName(), "");
        String fieldName = parameterName.indexOf('.') == -1 ? parameterName : parameterName.substring(0, parameterName.indexOf('.'));
        Field declaredField; 
        try {
            declaredField = originalMethodParam.getParameterType().getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            declaredField = originalMethodParam.getParameterType().getSuperclass().getDeclaredField(fieldName);
        }
        return Stream.of(declaredField.getAnnotations())
            .filter(annot -> List.of(Hidden.class, JsonIgnore.class).contains(annot.annotationType())).count() > 0;
    }
    

    【讨论】:

    • 你能解释一下如何应用这个变通方法吗?你修补 MethodParameterPojoExtractor 了吗?
    • 只需在 SwaggerConfig 类中创建一个GenericParameterService Bean,将方法delegatingMethodParameterCustomizer 传递给参数。再看答案,我刚刚插入了bean声明。
    猜你喜欢
    • 2021-02-27
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多