Skip to content

Commit 3842c17

Browse files
committed
fix: add so that the type annotation is considered again if kotlin is not present
#3215
1 parent a61f4fa commit 3842c17

9 files changed

Lines changed: 486 additions & 49 deletions

File tree

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

Lines changed: 26 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,18 @@
5050
import io.swagger.v3.oas.annotations.enums.ParameterIn;
5151
import io.swagger.v3.oas.annotations.enums.ParameterStyle;
5252
import io.swagger.v3.oas.annotations.extensions.Extension;
53+
import io.swagger.v3.oas.annotations.media.ArraySchema;
5354
import io.swagger.v3.oas.annotations.media.ExampleObject;
5455
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
56+
import io.swagger.v3.oas.annotations.parameters.RequestBody;
5557
import io.swagger.v3.oas.models.Components;
5658
import io.swagger.v3.oas.models.examples.Example;
5759
import io.swagger.v3.oas.models.media.Content;
5860
import io.swagger.v3.oas.models.media.FileSchema;
5961
import io.swagger.v3.oas.models.media.ObjectSchema;
6062
import io.swagger.v3.oas.models.media.Schema;
61-
import io.swagger.v3.oas.models.media.StringSchema;
6263
import io.swagger.v3.oas.models.parameters.Parameter;
64+
import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum;
6365
import org.apache.commons.lang3.StringUtils;
6466
import org.apache.commons.lang3.reflect.FieldUtils;
6567
import org.slf4j.Logger;
@@ -151,10 +153,10 @@ public class GenericParameterService {
151153
/**
152154
* Instantiates a new Generic parameter builder.
153155
*
154-
* @param propertyResolverUtils the property resolver utils
155-
* @param optionalWebConversionServiceProvider the optional web conversion service provider
156-
* @param objectMapperProvider the object mapper provider
157-
* @param javadocProviderOptional the javadoc provider
156+
* @param propertyResolverUtils the property resolver utils
157+
* @param optionalWebConversionServiceProvider the optional web conversion service provider
158+
* @param objectMapperProvider the object mapper provider
159+
* @param javadocProviderOptional the javadoc provider
158160
*/
159161
public GenericParameterService(PropertyResolverUtils propertyResolverUtils,
160162
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider, Optional<JavadocProvider> javadocProviderOptional) {
@@ -241,7 +243,7 @@ public static void mergeParameter(Parameter paramCalcul, Parameter paramDoc) {
241243
paramDoc.setAllowReserved(paramCalcul.getAllowReserved());
242244

243245
if (StringUtils.isBlank(paramDoc.get$ref()))
244-
paramDoc.set$ref(paramCalcul.get$ref());
246+
paramDoc.set$ref(paramDoc.get$ref());
245247

246248
if (paramDoc.getSchema() == null && paramDoc.getContent() == null)
247249
paramDoc.setSchema(paramCalcul.getSchema());
@@ -257,29 +259,6 @@ public static void mergeParameter(Parameter paramCalcul, Parameter paramDoc) {
257259

258260
if (paramDoc.getExplode() == null)
259261
paramDoc.setExplode(paramCalcul.getExplode());
260-
261-
if (paramDoc.getSchema() instanceof StringSchema existingSchema &&
262-
paramCalcul.getSchema() instanceof StringSchema newSchema) {
263-
264-
List<String> existingEnums = existingSchema.getEnum() != null
265-
? new ArrayList<>(existingSchema.getEnum())
266-
: new ArrayList<>();
267-
268-
List<String> newEnums = newSchema.getEnum();
269-
270-
if (newEnums != null && !newEnums.isEmpty()) {
271-
for (String val : newEnums) {
272-
if (!existingEnums.contains(val)) {
273-
existingEnums.add(val);
274-
}
275-
}
276-
existingSchema.setEnum(existingEnums);
277-
}
278-
279-
if (newSchema.getDefault() != null) {
280-
existingSchema.setDefault(newSchema.getDefault());
281-
}
282-
}
283262
}
284263

285264
/**
@@ -324,7 +303,7 @@ public Parameter buildParameterFromDoc(io.swagger.v3.oas.annotations.Parameter p
324303
optionalContent.ifPresent(parameter::setContent);
325304
}
326305
else
327-
setSchema(parameterDoc, components, jsonView, parameter, locale);
306+
setSchema(parameterDoc, components, jsonView, parameter);
328307

329308
setExamples(parameterDoc, parameter);
330309
setExtensions(parameterDoc, parameter, locale);
@@ -337,13 +316,12 @@ public Parameter buildParameterFromDoc(io.swagger.v3.oas.annotations.Parameter p
337316
/**
338317
* Sets schema.
339318
*
340-
* @param parameterDoc the parameter doc
341-
* @param components the components
342-
* @param jsonView the json view
343-
* @param parameter the parameter
344-
* @param locale the locale
319+
* @param parameterDoc the parameter doc
320+
* @param components the components
321+
* @param jsonView the json view
322+
* @param parameter the parameter
345323
*/
346-
private void setSchema(io.swagger.v3.oas.annotations.Parameter parameterDoc, Components components, JsonView jsonView, Parameter parameter, Locale locale) {
324+
private void setSchema(io.swagger.v3.oas.annotations.Parameter parameterDoc, Components components, JsonView jsonView, Parameter parameter) {
347325
if (StringUtils.isNotBlank(parameterDoc.ref()))
348326
parameter.$ref(parameterDoc.ref());
349327
else {
@@ -357,11 +335,7 @@ private void setSchema(io.swagger.v3.oas.annotations.Parameter parameterDoc, Com
357335
PrimitiveType primitiveType = PrimitiveType.fromTypeAndFormat(schema.getType(), schema.getFormat());
358336
if (primitiveType != null) {
359337
Schema<?> primitiveSchema = primitiveType.createProperty();
360-
if (schema.getDefault() instanceof String stringValue) {
361-
primitiveSchema.setDefault(propertyResolverUtils.resolve(stringValue, locale));
362-
} else {
363-
primitiveSchema.setDefault(schema.getDefault());
364-
}
338+
primitiveSchema.setDefault(schema.getDefault());
365339
schema.setDefault(primitiveSchema.getDefault());
366340
}
367341
}
@@ -399,7 +373,7 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
399373

400374
if (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getSchema() == null) {
401375
Type type = GenericTypeResolver.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass());
402-
Annotation[] paramAnnotations = getParameterAnnotations(methodParameter);
376+
Annotation[] paramAnnotations = getParameterAnnotations(methodParameter);
403377
Annotation[] typeAnnotations = new Annotation[0];
404378
if (KotlinDetector.isKotlinPresent()
405379
&& KotlinDetector.isKotlinReflectPresent()
@@ -411,6 +385,8 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
411385
type = restored;
412386
typeAnnotations = ((Class<?>) type).getAnnotations();
413387
}
388+
} else {
389+
typeAnnotations = methodParameter.getParameterType().getAnnotations();
414390
}
415391
Annotation[] mergedAnnotations =
416392
Stream.concat(
@@ -420,7 +396,8 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
420396
if (type instanceof Class && !((Class<?>) type).isEnum() && optionalWebConversionServiceProvider.isPresent()) {
421397
WebConversionServiceProvider webConversionServiceProvider = optionalWebConversionServiceProvider.get();
422398
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && Arrays.stream(mergedAnnotations)
423-
.noneMatch(a -> a.annotationType() == io.swagger.v3.oas.annotations.media.Schema.class)) { Class<?> springConvertedType = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
399+
.noneMatch(a -> a.annotationType() == io.swagger.v3.oas.annotations.media.Schema.class)) {
400+
Class<?> springConvertedType = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
424401
if (!(String.class.equals(springConvertedType) && ((Class<?>) type).isEnum()) && requestBodyInfo == null)
425402
type = springConvertedType;
426403
}
@@ -555,7 +532,7 @@ else if (Explode.FALSE.equals(p.explode())) {
555532
*/
556533
private void setParameterStyle(Parameter parameter, io.swagger.v3.oas.annotations.Parameter p) {
557534
if (StringUtils.isNotBlank(p.style().toString())) {
558-
parameter.setStyle(Parameter.StyleEnum.valueOf(p.style().toString().toUpperCase()));
535+
parameter.setStyle(StyleEnum.valueOf(p.style().toString().toUpperCase()));
559536
}
560537
}
561538

@@ -567,7 +544,7 @@ private void setParameterStyle(Parameter parameter, io.swagger.v3.oas.annotation
567544
*/
568545
private boolean isExplodable(io.swagger.v3.oas.annotations.Parameter p) {
569546
io.swagger.v3.oas.annotations.media.Schema schema = p.schema();
570-
io.swagger.v3.oas.annotations.media.ArraySchema arraySchema = p.array();
547+
ArraySchema arraySchema = p.array();
571548

572549
boolean explode = true;
573550
Class<?> implementation = schema.implementation();
@@ -715,7 +692,7 @@ public io.swagger.v3.oas.annotations.media.Schema schema() {
715692
}
716693

717694
@Override
718-
public io.swagger.v3.oas.annotations.media.ArraySchema array() {
695+
public ArraySchema array() {
719696
return null;
720697
}
721698

@@ -772,9 +749,9 @@ public JavadocProvider getJavadocProvider() {
772749
* @return the boolean
773750
*/
774751
public boolean isRequestBodyPresent(ParameterInfo parameterInfo) {
775-
return parameterInfo.getMethodParameter().getParameterAnnotation(io.swagger.v3.oas.annotations.parameters.RequestBody.class) != null
752+
return parameterInfo.getMethodParameter().getParameterAnnotation(RequestBody.class) != null
776753
|| parameterInfo.getMethodParameter().getParameterAnnotation(org.springframework.web.bind.annotation.RequestBody.class) != null
777-
|| AnnotatedElementUtils.findMergedAnnotation(Objects.requireNonNull(parameterInfo.getMethodParameter().getMethod()), io.swagger.v3.oas.annotations.parameters.RequestBody.class) != null;
754+
|| AnnotatedElementUtils.findMergedAnnotation(Objects.requireNonNull(parameterInfo.getMethodParameter().getMethod()), RequestBody.class) != null;
778755
}
779756

780757
/**
@@ -820,4 +797,4 @@ String getParamJavadoc(JavadocProvider javadocProvider, MethodParameter methodPa
820797
public boolean isOpenapi31() {
821798
return propertyResolverUtils.isOpenapi31();
822799
}
823-
}
800+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * *
7+
* * * * * * Copyright 2019-2025 the original author or authors.
8+
* * * * * *
9+
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
10+
* * * * * * you may not use this file except in compliance with the License.
11+
* * * * * * You may obtain a copy of the License at
12+
* * * * * *
13+
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
14+
* * * * * *
15+
* * * * * * Unless required by applicable law or agreed to in writing, software
16+
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
17+
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* * * * * * See the License for the specific language governing permissions and
19+
* * * * * * limitations under the License.
20+
* * * * *
21+
* * * *
22+
* * *
23+
* *
24+
*
25+
*/
26+
27+
package test.org.springdoc.api.v30.app248;
28+
29+
import java.util.UUID;
30+
31+
import io.swagger.v3.oas.annotations.media.Schema;
32+
33+
import org.springframework.web.bind.annotation.GetMapping;
34+
import org.springframework.web.bind.annotation.PathVariable;
35+
import org.springframework.web.bind.annotation.RestController;
36+
37+
@RestController
38+
public class HelloController {
39+
40+
@GetMapping(value = "/class-works/{regularSchema}")
41+
public RegularSchema dataClass1(@PathVariable RegularSchema regularSchema) {
42+
return null;
43+
}
44+
45+
@GetMapping(value = "/class-works2/{pathSchema}")
46+
public String dataClass2(@PathVariable PathSchema pathSchema) {
47+
return null;
48+
}
49+
50+
@GetMapping(value = "/class-works3/{itemId}")
51+
public String dataClass3(@PathVariable ItemId itemId) {
52+
return null;
53+
}
54+
}
55+
56+
@Schema(description = "regularSchema")
57+
record RegularSchema(String name, String value) {
58+
}
59+
60+
@Schema(description = "pathSchema", example = "123")
61+
record PathSchema(UUID value) {
62+
}
63+
64+
@Schema(
65+
type = "uuid",
66+
description = "Unique item identifier",
67+
example = "9d9d46e5-d41c-4774-885d-8e9dbc67735c")
68+
record ItemId(UUID value) {
69+
70+
public static ItemId fromString(String uuid) {
71+
return new ItemId(UUID.fromString(uuid));
72+
}
73+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package test.org.springdoc.api.v30.app248;
2+
3+
import org.springframework.core.convert.converter.Converter;
4+
import org.springframework.stereotype.Component;
5+
6+
@Component
7+
public class ItemIdConverter implements Converter<String, ItemId> {
8+
9+
@Override
10+
public ItemId convert(String source) {
11+
return ItemId.fromString(source);
12+
}
13+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * * Copyright 2025 the original author or authors.
7+
* * * * *
8+
* * * * * Licensed under the Apache License, Version 2.0 (the "License");
9+
* * * * * you may not use this file except in compliance with the License.
10+
* * * * * You may obtain a copy of the License at
11+
* * * * *
12+
* * * * * https://www.apache.org/licenses/LICENSE-2.0
13+
* * * * *
14+
* * * * * Unless required by applicable law or agreed to in writing, software
15+
* * * * * distributed under the License is distributed on an "AS IS" BASIS,
16+
* * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* * * * * See the License for the specific language governing permissions and
18+
* * * * * limitations under the License.
19+
* * * *
20+
* * *
21+
* *
22+
*
23+
*/
24+
25+
package test.org.springdoc.api.v30.app248;
26+
27+
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
28+
29+
import org.springframework.boot.autoconfigure.SpringBootApplication;
30+
31+
public class SpringDocApp248Test extends AbstractSpringDocV30Test {
32+
33+
@SpringBootApplication
34+
static class SpringDocTestApp {}
35+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * *
7+
* * * * * * Copyright 2019-2025 the original author or authors.
8+
* * * * * *
9+
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
10+
* * * * * * you may not use this file except in compliance with the License.
11+
* * * * * * You may obtain a copy of the License at
12+
* * * * * *
13+
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
14+
* * * * * *
15+
* * * * * * Unless required by applicable law or agreed to in writing, software
16+
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
17+
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* * * * * * See the License for the specific language governing permissions and
19+
* * * * * * limitations under the License.
20+
* * * * *
21+
* * * *
22+
* * *
23+
* *
24+
*
25+
*/
26+
27+
package test.org.springdoc.api.v31.app254;
28+
29+
import java.util.UUID;
30+
31+
import io.swagger.v3.oas.annotations.media.Schema;
32+
33+
import org.springframework.web.bind.annotation.GetMapping;
34+
import org.springframework.web.bind.annotation.PathVariable;
35+
import org.springframework.web.bind.annotation.RestController;
36+
37+
@RestController
38+
public class HelloController {
39+
40+
@GetMapping(value = "/class-works/{regularSchema}")
41+
public RegularSchema dataClass1(@PathVariable RegularSchema regularSchema) {
42+
return null;
43+
}
44+
45+
@GetMapping(value = "/class-works2/{pathSchema}")
46+
public String dataClass2(@PathVariable PathSchema pathSchema) {
47+
return null;
48+
}
49+
50+
@GetMapping(value = "/class-works3/{itemId}")
51+
public String dataClass3(@PathVariable ItemId itemId) {
52+
return null;
53+
}
54+
}
55+
56+
@Schema(description = "regularSchema")
57+
record RegularSchema(String name, String value) {
58+
}
59+
60+
@Schema(description = "pathSchema", example = "123")
61+
record PathSchema(UUID value) {
62+
}
63+
64+
@Schema(
65+
type = "uuid",
66+
description = "Unique item identifier",
67+
example = "9d9d46e5-d41c-4774-885d-8e9dbc67735c")
68+
record ItemId(UUID value) {
69+
70+
public static ItemId fromString(String uuid) {
71+
return new ItemId(UUID.fromString(uuid));
72+
}
73+
}

0 commit comments

Comments
 (0)