Skip to content

Commit 3ef246d

Browse files
committed
Merge branch 'default-flat-object' of github.com:NaccOll/springdoc-openapi into NaccOll-default-flat-object
2 parents fb02518 + 6720e1e commit 3ef246d

File tree

10 files changed

+120
-51
lines changed

10 files changed

+120
-51
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractRequestService.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ protected AbstractRequestService(GenericParameterService parameterBuilder, Reque
185185
parameterCustomizers.ifPresent(customizers -> customizers.removeIf(Objects::isNull));
186186
this.parameterCustomizers = parameterCustomizers;
187187
this.localSpringDocParameterNameDiscoverer = localSpringDocParameterNameDiscoverer;
188+
parameterBuilder.addIgnoreType(PARAM_TYPES_TO_IGNORE);
188189
}
189190

190191
/**
@@ -239,7 +240,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
239240
String[] reflectionParametersNames = Arrays.stream(handlerMethod.getMethod().getParameters()).map(java.lang.reflect.Parameter::getName).toArray(String[]::new);
240241
if (pNames == null || Arrays.stream(pNames).anyMatch(Objects::isNull))
241242
pNames = reflectionParametersNames;
242-
parameters = DelegatingMethodParameter.customize(pNames, parameters, parameterBuilder.getDelegatingMethodParameterCustomizer());
243+
parameters = parameterBuilder.customize(pNames, parameters, parameterBuilder.getDelegatingMethodParameterCustomizer());
243244
RequestBodyInfo requestBodyInfo = new RequestBodyInfo();
244245
List<Parameter> operationParameters = (operation.getParameters() != null) ? operation.getParameters() : new ArrayList<>();
245246
Map<String, io.swagger.v3.oas.annotations.Parameter> parametersDocMap = getApiParameters(handlerMethod.getMethod());
@@ -322,7 +323,7 @@ else if (!RequestMethod.GET.equals(requestMethod)) {
322323
Entry<String, Parameter> entry = it.next();
323324
Parameter parameter = entry.getValue();
324325
if (!ParameterIn.PATH.toString().equals(parameter.getIn())) {
325-
io.swagger.v3.oas.models.media.Schema<?> itemSchema = new io.swagger.v3.oas.models.media.Schema() ;
326+
io.swagger.v3.oas.models.media.Schema<?> itemSchema = new io.swagger.v3.oas.models.media.Schema();
326327
itemSchema.setName(entry.getKey());
327328
itemSchema.setDescription(parameter.getDescription());
328329
itemSchema.setDeprecated(parameter.getDeprecated());

springdoc-openapi-common/src/main/java/org/springdoc/core/DelegatingMethodParameter.java

+1-35
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,16 @@
2929
import java.lang.reflect.Member;
3030
import java.lang.reflect.Method;
3131
import java.lang.reflect.Type;
32-
import java.util.ArrayList;
3332
import java.util.Arrays;
34-
import java.util.List;
3533
import java.util.Objects;
36-
import java.util.Optional;
3734

3835
import org.apache.commons.lang3.ArrayUtils;
3936
import org.apache.commons.lang3.reflect.FieldUtils;
4037
import org.slf4j.Logger;
4138
import org.slf4j.LoggerFactory;
42-
import org.springdoc.api.annotations.ParameterObject;
43-
import org.springdoc.core.converters.AdditionalModelsConverter;
44-
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
4539

4640
import org.springframework.core.MethodParameter;
4741
import org.springframework.core.ParameterNameDiscoverer;
48-
import org.springframework.core.annotation.AnnotatedElementUtils;
4942
import org.springframework.lang.NonNull;
5043
import org.springframework.lang.Nullable;
5144

@@ -103,33 +96,6 @@ public class DelegatingMethodParameter extends MethodParameter {
10396
this.isNotRequired = isNotRequired;
10497
}
10598

106-
/**
107-
* Customize method parameter [ ].
108-
*
109-
* @param pNames the p names
110-
* @param parameters the parameters
111-
* @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
112-
* @return the method parameter [ ]
113-
*/
114-
public static MethodParameter[] customize(String[] pNames, MethodParameter[] parameters, Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer) {
115-
List<MethodParameter> explodedParameters = new ArrayList<>();
116-
for (int i = 0; i < parameters.length; ++i) {
117-
MethodParameter p = parameters[i];
118-
Class<?> paramClass = AdditionalModelsConverter.getParameterObjectReplacement(p.getParameterType());
119-
120-
if (!MethodParameterPojoExtractor.isSimpleType(paramClass) && (p.hasParameterAnnotation(ParameterObject.class) || AnnotatedElementUtils.isAnnotated(paramClass, ParameterObject.class))) {
121-
MethodParameterPojoExtractor.extractFrom(paramClass).forEach(methodParameter -> {
122-
optionalDelegatingMethodParameterCustomizer.ifPresent(customizer -> customizer.customize(p, methodParameter));
123-
explodedParameters.add(methodParameter);
124-
});
125-
}
126-
else {
127-
String name = pNames != null ? pNames[i] : p.getParameterName();
128-
explodedParameters.add(new DelegatingMethodParameter(p, name, null, false, false));
129-
}
130-
}
131-
return explodedParameters.toArray(new MethodParameter[0]);
132-
}
13399

134100
@Override
135101
@NonNull
@@ -274,4 +240,4 @@ public static MethodParameter changeContainingClass(MethodParameter methodParame
274240
return result;
275241
}
276242

277-
}
243+
}

springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java

+62-3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
import org.apache.commons.lang3.StringUtils;
5656
import org.slf4j.Logger;
5757
import org.slf4j.LoggerFactory;
58+
import org.springdoc.api.annotations.ParameterObject;
59+
import org.springdoc.core.converters.AdditionalModelsConverter;
5860
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
5961
import org.springdoc.core.providers.ObjectMapperProvider;
6062
import org.springdoc.core.providers.WebConversionServiceProvider;
@@ -64,6 +66,7 @@
6466
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
6567
import org.springframework.core.MethodParameter;
6668
import org.springframework.core.ResolvableType;
69+
import org.springframework.core.annotation.AnnotatedElementUtils;
6770
import org.springframework.core.io.Resource;
6871
import org.springframework.web.context.request.RequestScope;
6972
import org.springframework.web.multipart.MultipartFile;
@@ -122,6 +125,13 @@ public class GenericParameterService {
122125
*/
123126
private final ObjectMapperProvider objectMapperProvider;
124127

128+
/**
129+
* The constant PARAM_TYPES_TO_IGNORE.
130+
*/
131+
private final List<Class<?>> PARAM_TYPES_TO_IGNORE = Collections.synchronizedList(new ArrayList<>());
132+
133+
private final boolean defaultFlatParamObject;
134+
125135
/**
126136
* Instantiates a new Generic parameter builder.
127137
* @param propertyResolverUtils the property resolver utils
@@ -130,13 +140,18 @@ public class GenericParameterService {
130140
* @param objectMapperProvider the object mapper provider
131141
*/
132142
public GenericParameterService(PropertyResolverUtils propertyResolverUtils, Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer,
133-
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider) {
143+
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider, boolean defaultFlatParamObject) {
134144
this.propertyResolverUtils = propertyResolverUtils;
135145
this.optionalDelegatingMethodParameterCustomizer = optionalDelegatingMethodParameterCustomizer;
136146
this.optionalWebConversionServiceProvider = optionalWebConversionServiceProvider;
137147
this.configurableBeanFactory = propertyResolverUtils.getFactory();
138148
this.expressionContext = (configurableBeanFactory != null ? new BeanExpressionContext(configurableBeanFactory, new RequestScope()) : null);
139149
this.objectMapperProvider = objectMapperProvider;
150+
this.defaultFlatParamObject = defaultFlatParamObject;
151+
}
152+
153+
protected void addIgnoreType(List<Class<?>> classes) {
154+
PARAM_TYPES_TO_IGNORE.addAll(classes);
140155
}
141156

142157
/**
@@ -333,9 +348,9 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
333348

334349
if (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getSchema() == null) {
335350
Type type = ReturnTypeParser.getType(methodParameter);
336-
if(type instanceof Class && optionalWebConversionServiceProvider.isPresent()){
351+
if (type instanceof Class && optionalWebConversionServiceProvider.isPresent()) {
337352
WebConversionServiceProvider webConversionServiceProvider = optionalWebConversionServiceProvider.get();
338-
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class)==null)
353+
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null)
339354
type = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
340355
}
341356
schemaN = SpringDocAnnotationsUtils.extractSchema(components, type, jsonView, methodParameter.getParameterAnnotations());
@@ -566,6 +581,7 @@ public io.swagger.v3.oas.annotations.Parameter generateParameterBySchema(io.swag
566581
public Class<? extends Annotation> annotationType() {
567582
return io.swagger.v3.oas.annotations.Parameter.class;
568583
}
584+
569585
@Override
570586
public String name() {
571587
return schema.name();
@@ -652,4 +668,47 @@ public String ref() {
652668
}
653669
};
654670
}
671+
672+
/**
673+
* Customize method parameter [ ].
674+
*
675+
* @param pNames the p names
676+
* @param parameters the parameters
677+
* @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
678+
* @return the method parameter [ ]
679+
*/
680+
public MethodParameter[] customize(String[] pNames, MethodParameter[] parameters, Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer) {
681+
List<MethodParameter> explodedParameters = new ArrayList<>();
682+
for (int i = 0; i < parameters.length; ++i) {
683+
MethodParameter p = parameters[i];
684+
Class<?> paramClass = AdditionalModelsConverter.getParameterObjectReplacement(p.getParameterType());
685+
if (!MethodParameterPojoExtractor.isSimpleType(paramClass) && (p.hasParameterAnnotation(ParameterObject.class) || AnnotatedElementUtils.isAnnotated(paramClass, ParameterObject.class))) {
686+
MethodParameterPojoExtractor.extractFrom(paramClass).forEach(methodParameter -> {
687+
optionalDelegatingMethodParameterCustomizer.ifPresent(customizer -> customizer.customize(p, methodParameter));
688+
explodedParameters.add(methodParameter);
689+
});
690+
}
691+
else if (defaultFlatParamObject) {
692+
boolean isSimpleType = MethodParameterPojoExtractor.isSimpleType(paramClass);
693+
boolean hasAnnotation = p.hasParameterAnnotations();
694+
boolean shouldFlat = !isSimpleType && !hasAnnotation;
695+
if (shouldFlat && PARAM_TYPES_TO_IGNORE.stream().noneMatch(ignore -> ignore.isAssignableFrom(paramClass))) {
696+
MethodParameterPojoExtractor.extractFrom(paramClass).forEach(methodParameter -> {
697+
optionalDelegatingMethodParameterCustomizer
698+
.ifPresent(customizer -> customizer.customize(p, methodParameter));
699+
explodedParameters.add(methodParameter);
700+
});
701+
}
702+
else {
703+
String name = pNames != null ? pNames[i] : p.getParameterName();
704+
explodedParameters.add(new DelegatingMethodParameter(p, name, null, false, false));
705+
}
706+
}
707+
else {
708+
String name = pNames != null ? pNames[i] : p.getParameterName();
709+
explodedParameters.add(new DelegatingMethodParameter(p, name, null, false, false));
710+
}
711+
}
712+
return explodedParameters.toArray(new MethodParameter[0]);
713+
}
655714
}

springdoc-openapi-common/src/main/java/org/springdoc/core/MethodParameterPojoExtractor.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.lang.reflect.Field;
2929
import java.lang.reflect.Type;
3030
import java.lang.reflect.TypeVariable;
31+
import java.nio.charset.Charset;
3132
import java.time.Duration;
3233
import java.time.LocalTime;
3334
import java.util.ArrayList;
@@ -83,6 +84,7 @@ private MethodParameterPojoExtractor() {
8384
SIMPLE_TYPES.add(OptionalDouble.class);
8485
SIMPLE_TYPES.add(AtomicLong.class);
8586
SIMPLE_TYPES.add(AtomicInteger.class);
87+
SIMPLE_TYPES.add(Charset.class);
8688

8789
SIMPLE_TYPES.add(Map.class);
8890
SIMPLE_TYPES.add(Iterable.class);
@@ -154,7 +156,7 @@ private static Class<?> extractType(Class<?> paramClass, Field field) {
154156

155157
if (fieldType instanceof Class<?>)
156158
type = (Class<?>) fieldType;
157-
else // This is the case for not reifiable types
159+
else // This is the case for not reifiable types
158160
type = null;
159161
}
160162

@@ -173,7 +175,7 @@ private static Stream<MethodParameter> fromSimpleClass(Class<?> paramClass, Fiel
173175
Annotation[] fieldAnnotations = field.getDeclaredAnnotations();
174176
try {
175177
Parameter parameter = field.getAnnotation(Parameter.class);
176-
boolean isNotRequired = parameter == null || !parameter.required();
178+
boolean isNotRequired = parameter == null || !parameter.required();
177179
Annotation[] finalFieldAnnotations = fieldAnnotations;
178180
return Stream.of(Introspector.getBeanInfo(paramClass).getPropertyDescriptors())
179181
.filter(d -> d.getName().equals(field.getName()))

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfigProperties.java

+17
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ public class SpringDocConfigProperties {
176176
*/
177177
private boolean showSpringCloudFunctions;
178178

179+
/**
180+
* The param default flatten
181+
*/
182+
private boolean defaultFlatParamObject;
183+
179184
/**
180185
* The model Converters
181186
*/
@@ -222,6 +227,18 @@ public void setShowSpringCloudFunctions(boolean showSpringCloudFunctions) {
222227
this.showSpringCloudFunctions = showSpringCloudFunctions;
223228
}
224229

230+
/**
231+
* Is default flat param object
232+
* @return the boolean
233+
*/
234+
public boolean isDefaultFlatParamObject() {
235+
return defaultFlatParamObject;
236+
}
237+
238+
public void setDefaultFlatParamObject(boolean defaultFlatParamObject) {
239+
this.defaultFlatParamObject = defaultFlatParamObject;
240+
}
241+
225242
/**
226243
* Gets model converters.
227244
*

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfiguration.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ PolymorphicModelConverter polymorphicModelConverter(ObjectMapperProvider objectM
240240
@Lazy(false)
241241
OpenAPIService openAPIBuilder(Optional<OpenAPI> openAPI,
242242
SecurityService securityParser,
243-
SpringDocConfigProperties springDocConfigProperties,PropertyResolverUtils propertyResolverUtils,
243+
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
244244
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,
245245
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) {
246246
return new OpenAPIService(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);
@@ -335,16 +335,18 @@ ReturnTypeParser genericReturnTypeParser() {
335335
* @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
336336
* @param optionalWebConversionServiceProvider the optional web conversion service provider
337337
* @param objectMapperProvider the object mapper provider
338+
* @param springDocConfigProperties the springdoc config properties
338339
* @return the generic parameter builder
339340
*/
340341
@Bean
341342
@ConditionalOnMissingBean
342343
@Lazy(false)
343344
GenericParameterService parameterBuilder(PropertyResolverUtils propertyResolverUtils,
344345
Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer,
345-
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider) {
346+
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider,
347+
SpringDocConfigProperties springDocConfigProperties) {
346348
return new GenericParameterService(propertyResolverUtils, optionalDelegatingMethodParameterCustomizer,
347-
optionalWebConversionServiceProvider, objectMapperProvider);
349+
optionalWebConversionServiceProvider, objectMapperProvider, springDocConfigProperties.isDefaultFlatParamObject());
348350
}
349351

350352
/**
@@ -411,7 +413,7 @@ static BeanFactoryPostProcessor springdocBeanFactoryPostProcessor2() {
411413
@Lazy(false)
412414
SpringDocProviders springDocProviders(Optional<ActuatorProvider> actuatorProvider, Optional<CloudFunctionProvider> springCloudFunctionProvider, Optional<SecurityOAuth2Provider> springSecurityOAuth2Provider,
413415
Optional<RepositoryRestResourceProvider> repositoryRestResourceProvider, Optional<RouterFunctionProvider> routerFunctionProvider,
414-
Optional<SpringWebProvider> springWebProvider, Optional<WebConversionServiceProvider> webConversionServiceProvider,
416+
Optional<SpringWebProvider> springWebProvider, Optional<WebConversionServiceProvider> webConversionServiceProvider,
415417
ObjectMapperProvider objectMapperProvider) {
416418
return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider, springWebProvider, webConversionServiceProvider, objectMapperProvider);
417419
}
@@ -611,7 +613,7 @@ CloudFunctionProvider springCloudFunctionProvider(Optional<FunctionCatalog> func
611613
@Bean
612614
@ConditionalOnMissingBean
613615
@Lazy(false)
614-
ObjectMapperProvider springDocObjectMapperProvider(SpringDocConfigProperties springDocConfigProperties){
616+
ObjectMapperProvider springDocObjectMapperProvider(SpringDocConfigProperties springDocConfigProperties) {
615617
return new ObjectMapperProvider(springDocConfigProperties);
616618
}
617619

springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestService.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import io.swagger.v3.oas.models.parameters.Parameter;
4141
import org.apache.commons.lang3.ArrayUtils;
4242
import org.springdoc.core.AbstractRequestService;
43-
import org.springdoc.core.DelegatingMethodParameter;
4443
import org.springdoc.core.GenericParameterService;
4544
import org.springdoc.core.MethodAttributes;
4645
import org.springdoc.core.ParameterInfo;
@@ -149,7 +148,7 @@ public void buildParameters(OpenAPI openAPI, HandlerMethod handlerMethod, Reques
149148
*/
150149
public void buildCommonParameters(OpenAPI openAPI, RequestMethod requestMethod, MethodAttributes methodAttributes, Operation operation, String[] pNames, MethodParameter[] parameters,
151150
DataRestRepository dataRestRepository) {
152-
parameters = DelegatingMethodParameter.customize(pNames, parameters, parameterBuilder.getDelegatingMethodParameterCustomizer());
151+
parameters = parameterBuilder.customize(pNames, parameters, parameterBuilder.getDelegatingMethodParameterCustomizer());
153152
Class<?> domainType = dataRestRepository.getDomainType();
154153
for (MethodParameter methodParameter : parameters) {
155154
final String pName = methodParameter.getParameterName();

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app71/Dog.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,11 @@ public class Dog {
3737
)
3838
String displayName;
3939

40-
}
40+
public String getDisplayName() {
41+
return displayName;
42+
}
43+
44+
public void setDisplayName(String displayName) {
45+
this.displayName = displayName;
46+
}
47+
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app93/BaseClientModel.java

+8
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@
2727
public abstract class BaseClientModel {
2828
@JsonProperty("id")
2929
int id;
30+
31+
public int getId() {
32+
return id;
33+
}
34+
35+
public void setId(int id) {
36+
this.id = id;
37+
}
3038
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/v30/app93/SpecificClientModel.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,12 @@
2727
public class SpecificClientModel extends BaseClientModel {
2828
@JsonProperty("name")
2929
String name;
30-
}
30+
31+
public String getName() {
32+
return name;
33+
}
34+
35+
public void setName(String name) {
36+
this.name = name;
37+
}
38+
}

0 commit comments

Comments
 (0)