Skip to content

Commit 8138180

Browse files
authored
Merge branch 'master' into coreCleanU
2 parents 7b6f75e + 95d2522 commit 8138180

File tree

43 files changed

+911
-165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+911
-165
lines changed

modules/swagger-annotations/src/main/java/io/swagger/v3/oas/annotations/media/Schema.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@
237237
/**
238238
* Allows to specify the access mode (AccessMode.READ_ONLY, READ_WRITE)
239239
*
240-
* AccessMode.READ_ONLY: value will only be written to during a request but not returned during a response.
240+
* AccessMode.READ_ONLY: value will not be written to during a request but may be returned during a response.
241241
* AccessMode.WRITE_ONLY: value will only be written to during a request but not returned during a response.
242242
* AccessMode.READ_WRITE: value will be written to during a request and returned during a response.
243243
*

modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java

+22-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.fasterxml.jackson.annotation.JsonProperty;
88
import com.fasterxml.jackson.annotation.JsonTypeInfo;
99
import com.fasterxml.jackson.annotation.JsonUnwrapped;
10+
import com.fasterxml.jackson.annotation.JsonValue;
1011
import com.fasterxml.jackson.annotation.JsonView;
1112
import com.fasterxml.jackson.annotation.ObjectIdGenerator;
1213
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@@ -81,6 +82,7 @@
8182
import java.util.LinkedHashMap;
8283
import java.util.List;
8384
import java.util.Map;
85+
import java.util.Optional;
8486
import java.util.Set;
8587
import java.util.stream.Collectors;
8688
import java.util.stream.Stream;
@@ -938,11 +940,29 @@ protected void _addEnumProps(Class<?> propClass, Schema property) {
938940
final boolean useIndex = _mapper.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX);
939941
final boolean useToString = _mapper.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
940942

943+
944+
Optional<Method> jsonValueMethod = Arrays.stream(propClass.getMethods())
945+
.filter(m -> m.isAnnotationPresent(JsonValue.class))
946+
.filter(m -> m.getAnnotation(JsonValue.class).value())
947+
.findFirst();
948+
941949
@SuppressWarnings("unchecked")
942950
Class<Enum<?>> enumClass = (Class<Enum<?>>) propClass;
943-
for (Enum<?> en : enumClass.getEnumConstants()) {
951+
952+
Enum<?>[] enumConstants = enumClass.getEnumConstants();
953+
String[] enumValues = _intr.findEnumValues(propClass, enumConstants, new String[enumConstants.length]);
954+
955+
for (Enum<?> en : enumConstants) {
944956
String n;
945-
if (useIndex) {
957+
958+
String enumValue = enumValues[en.ordinal()];
959+
String s = jsonValueMethod.flatMap(m -> ReflectionUtils.safeInvoke(m, en)).map(Object::toString).orElse(null);
960+
961+
if (s != null) {
962+
n = s;
963+
} else if (enumValue != null) {
964+
n = enumValue;
965+
} else if (useIndex) {
946966
n = String.valueOf(en.ordinal());
947967
} else if (useToString) {
948968
n = en.toString();

modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -555,15 +555,19 @@ public static Schema resolveSchemaFromType(Class<?> schemaImplementation, Compon
555555
Map<String, Schema> schemaMap;
556556
if (resolvedSchema != null) {
557557
schemaMap = resolvedSchema.referencedSchemas;
558-
schemaMap.forEach((key, referencedSchema) -> {
559-
if (components != null) {
560-
components.addSchemas(key, referencedSchema);
558+
if (schemaMap != null) {
559+
schemaMap.forEach((key, referencedSchema) -> {
560+
if (components != null) {
561+
components.addSchemas(key, referencedSchema);
562+
}
563+
});
564+
}
565+
if (resolvedSchema.schema != null) {
566+
if (StringUtils.isNotBlank(resolvedSchema.schema.getName())) {
567+
schemaObject.set$ref(COMPONENTS_REF + resolvedSchema.schema.getName());
568+
} else {
569+
schemaObject = resolvedSchema.schema;
561570
}
562-
});
563-
if (StringUtils.isNotBlank(resolvedSchema.schema.getName())) {
564-
schemaObject.set$ref(COMPONENTS_REF + resolvedSchema.schema.getName());
565-
} else {
566-
schemaObject = resolvedSchema.schema;
567571
}
568572
}
569573
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/ParameterProcessor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import java.lang.annotation.Annotation;
2222
import java.lang.reflect.Type;
2323
import java.util.ArrayList;
24-
import java.util.HashMap;
24+
import java.util.LinkedHashMap;
2525
import java.util.List;
2626
import java.util.Map;
2727
import java.util.Optional;
@@ -107,7 +107,7 @@ public static Parameter applyAnnotations(
107107
parameter.setAllowReserved(p.allowReserved());
108108
}
109109

110-
Map<String, Example> exampleMap = new HashMap<>();
110+
Map<String, Example> exampleMap = new LinkedHashMap<>();
111111
if (p.examples().length == 1 && StringUtils.isBlank(p.examples()[0].name())) {
112112
Optional<Example> exampleOptional = AnnotationsUtils.getExample(p.examples()[0], true);
113113
if (exampleOptional.isPresent()) {

modules/swagger-core/src/main/java/io/swagger/v3/core/util/ReflectionUtils.java

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.lang.annotation.Annotation;
1010
import java.lang.reflect.Constructor;
1111
import java.lang.reflect.Field;
12+
import java.lang.reflect.InvocationTargetException;
1213
import java.lang.reflect.Method;
1314
import java.lang.reflect.Modifier;
1415
import java.lang.reflect.Type;
@@ -17,6 +18,7 @@
1718
import java.util.Collections;
1819
import java.util.HashSet;
1920
import java.util.List;
21+
import java.util.Optional;
2022
import java.util.Set;
2123

2224
public class ReflectionUtils {
@@ -366,4 +368,13 @@ public static boolean isSystemType(JavaType type) {
366368
}
367369
return type.isArrayType();
368370
}
371+
372+
public static Optional<Object> safeInvoke(Method method, Object obj, Object... args) {
373+
try {
374+
return Optional.ofNullable(method.invoke(obj, args));
375+
} catch (IllegalAccessException | InvocationTargetException e) {
376+
return Optional.empty();
377+
}
378+
379+
}
369380
}

modules/swagger-core/src/test/java/io/swagger/v3/core/converting/EnumPropertyTest.java

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.swagger.v3.core.oas.models.ModelWithEnumField;
1111
import io.swagger.v3.core.oas.models.ModelWithEnumProperty;
1212
import io.swagger.v3.core.oas.models.ModelWithEnumRefProperty;
13+
import io.swagger.v3.core.oas.models.ModelWithJacksonEnumField;
1314
import io.swagger.v3.oas.models.media.Schema;
1415
import io.swagger.v3.oas.models.media.StringSchema;
1516
import org.testng.annotations.AfterTest;
@@ -156,4 +157,25 @@ public void testEnumRefPropertyGlobalNotAffectingNonEnums() {
156157
SerializationMatchers.assertEqualsToYaml(models, yaml);
157158
ModelResolver.enumsAsRef = false;
158159
}
160+
161+
@Test(description = "it should extract enum values from fields using JsonProperty and JsonValue")
162+
public void testExtractJacksonEnumFields() {
163+
final Map<String, Schema> models = ModelConverters.getInstance().read(ModelWithJacksonEnumField.class);
164+
final Schema model = models.get("ModelWithJacksonEnumField");
165+
166+
final Schema firstEnumProperty = (Schema) model.getProperties().get("firstEnumValue");
167+
assertTrue(firstEnumProperty instanceof StringSchema);
168+
final StringSchema stringProperty = (StringSchema) firstEnumProperty;
169+
assertEquals(stringProperty.getEnum(), Arrays.asList("p1", "p2", "SYSTEM", "INVITE_ONLY"));
170+
171+
final Schema secondEnumProperty = (Schema) model.getProperties().get("secondEnumValue");
172+
assertTrue(secondEnumProperty instanceof StringSchema);
173+
final StringSchema secondStringProperty = (StringSchema) secondEnumProperty;
174+
assertEquals(secondStringProperty.getEnum(), Arrays.asList("one", "two", "three"));
175+
176+
final Schema thirdEnumProperty = (Schema) model.getProperties().get("thirdEnumValue");
177+
assertTrue(thirdEnumProperty instanceof StringSchema);
178+
final StringSchema thirdStringProperty = (StringSchema) thirdEnumProperty;
179+
assertEquals(thirdStringProperty.getEnum(), Arrays.asList("2", "4", "6"));
180+
}
159181
}

modules/swagger-core/src/test/java/io/swagger/v3/core/deserialization/JsonDeserializationTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ public void deserializeLongSchema() throws IOException {
256256
assertEquals(s.getEnum().get(0), 2147483647);
257257
assertEquals(s.getEnum().get(1), 3147483647L);
258258
assertEquals(s.getEnum().get(2), 31474836475505055L);
259+
assertEquals(s.getEnum().get(3), -9223372036854775808L);
259260
}
260261

261262
@Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.swagger.v3.core.oas.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonValue;
4+
5+
public enum JacksonNumberValueEnum {
6+
FIRST(2),
7+
SECOND(4),
8+
THIRD(6);
9+
10+
private final int value;
11+
12+
JacksonNumberValueEnum(int value) {
13+
this.value = value;
14+
}
15+
16+
@JsonValue
17+
public Number getValue() {
18+
return value;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.swagger.v3.core.oas.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
5+
public enum JacksonPropertyEnum {
6+
@JsonProperty("p1") PRIVATE,
7+
@JsonProperty("p2") PUBLIC,
8+
SYSTEM,
9+
INVITE_ONLY
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.swagger.v3.core.oas.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonValue;
4+
5+
public enum JacksonValueEnum {
6+
FIRST("one"),
7+
SECOND("two"),
8+
THIRD("three");
9+
10+
private final String value;
11+
12+
JacksonValueEnum(String value) {
13+
this.value = value;
14+
}
15+
16+
@JsonValue
17+
public String getValue() {
18+
return value;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.swagger.v3.core.oas.models;
2+
3+
public class ModelWithJacksonEnumField {
4+
public JacksonPropertyEnum firstEnumValue;
5+
public JacksonValueEnum secondEnumValue;
6+
public JacksonNumberValueEnum thirdEnumValue;
7+
}

modules/swagger-core/src/test/resources/specFiles/oas3_2.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@ paths:
912912
- 2147483647
913913
- 3147483647
914914
- 31474836475505055
915+
- -9223372036854775808
915916
responses:
916917
'200':
917918
description: success!

modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/DefaultParameterExtension.java

+42-19
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@
55
import com.fasterxml.jackson.databind.ObjectMapper;
66
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
77
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
8+
import com.fasterxml.jackson.databind.introspect.AnnotationMap;
89
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
10+
911
import io.swagger.v3.core.util.Json;
1012
import io.swagger.v3.core.util.ParameterProcessor;
1113
import io.swagger.v3.jaxrs2.ext.AbstractOpenAPIExtension;
1214
import io.swagger.v3.jaxrs2.ext.OpenAPIExtension;
1315
import io.swagger.v3.jaxrs2.ext.OpenAPIExtensions;
16+
import io.swagger.v3.oas.annotations.Hidden;
1417
import io.swagger.v3.oas.models.Components;
1518
import io.swagger.v3.oas.models.parameters.Parameter;
1619
import org.apache.commons.lang3.StringUtils;
1720

1821
import javax.ws.rs.BeanParam;
1922
import javax.ws.rs.CookieParam;
20-
import javax.ws.rs.FormParam;
2123
import javax.ws.rs.HeaderParam;
2224
import javax.ws.rs.PathParam;
2325
import javax.ws.rs.QueryParam;
@@ -30,11 +32,10 @@
3032
import java.util.Set;
3133

3234
public class DefaultParameterExtension extends AbstractOpenAPIExtension {
33-
private static String QUERY_PARAM = "query";
34-
private static String HEADER_PARAM = "header";
35-
private static String COOKIE_PARAM = "cookie";
36-
private static String PATH_PARAM = "path";
37-
private static String FORM_PARAM = "form";
35+
private static final String QUERY_PARAM = "query";
36+
private static final String HEADER_PARAM = "header";
37+
private static final String COOKIE_PARAM = "cookie";
38+
private static final String PATH_PARAM = "path";
3839

3940
final ObjectMapper mapper = Json.mapper();
4041

@@ -169,17 +170,19 @@ private boolean handleAdditionalAnnotation(List<Parameter> parameters, List<Para
169170
final AnnotatedField field = propDef.getField();
170171
final AnnotatedMethod setter = propDef.getSetter();
171172
final AnnotatedMethod getter = propDef.getGetter();
172-
final List<Annotation> paramAnnotations = new ArrayList<Annotation>();
173+
final List<Annotation> paramAnnotations = new ArrayList<>();
173174
final Iterator<OpenAPIExtension> extensions = OpenAPIExtensions.chain();
174175
Type paramType = null;
175176

176177
// Gather the field's details
177178
if (field != null) {
178179
paramType = field.getType();
179-
180-
for (final Annotation fieldAnnotation : field.annotations()) {
181-
if (!paramAnnotations.contains(fieldAnnotation)) {
182-
paramAnnotations.add(fieldAnnotation);
180+
AnnotationMap annotationMap = field.getAllAnnotations();
181+
if (annotationMap != null) {
182+
for (final Annotation fieldAnnotation : annotationMap.annotations()) {
183+
if (!paramAnnotations.contains(fieldAnnotation)) {
184+
paramAnnotations.add(fieldAnnotation);
185+
}
183186
}
184187
}
185188
}
@@ -191,10 +194,12 @@ private boolean handleAdditionalAnnotation(List<Parameter> parameters, List<Para
191194
// paramType will stay null if there is no parameter
192195
paramType = setter.getParameterType(0);
193196
}
194-
195-
for (final Annotation fieldAnnotation : setter.annotations()) {
196-
if (!paramAnnotations.contains(fieldAnnotation)) {
197-
paramAnnotations.add(fieldAnnotation);
197+
AnnotationMap annotationMap = setter.getAllAnnotations();
198+
if (annotationMap != null) {
199+
for (final Annotation fieldAnnotation : annotationMap.annotations()) {
200+
if (!paramAnnotations.contains(fieldAnnotation)) {
201+
paramAnnotations.add(fieldAnnotation);
202+
}
198203
}
199204
}
200205
}
@@ -205,10 +210,12 @@ private boolean handleAdditionalAnnotation(List<Parameter> parameters, List<Para
205210
if (paramType == null) {
206211
paramType = getter.getType();
207212
}
208-
209-
for (final Annotation fieldAnnotation : getter.annotations()) {
210-
if (!paramAnnotations.contains(fieldAnnotation)) {
211-
paramAnnotations.add(fieldAnnotation);
213+
AnnotationMap annotationMap = getter.getAllAnnotations();
214+
if (annotationMap != null) {
215+
for (final Annotation fieldAnnotation : annotationMap.annotations()) {
216+
if (!paramAnnotations.contains(fieldAnnotation)) {
217+
paramAnnotations.add(fieldAnnotation);
218+
}
212219
}
213220
}
214221
}
@@ -217,6 +224,22 @@ private boolean handleAdditionalAnnotation(List<Parameter> parameters, List<Para
217224
continue;
218225
}
219226

227+
// skip hidden properties
228+
boolean hidden = false;
229+
for (Annotation a : paramAnnotations) {
230+
if (a instanceof io.swagger.v3.oas.annotations.media.Schema) {
231+
if (((io.swagger.v3.oas.annotations.media.Schema) a).hidden()) {
232+
hidden = true;
233+
break;
234+
};
235+
} else if (a instanceof Hidden) {
236+
hidden = true;
237+
break;
238+
}
239+
}
240+
if (hidden) {
241+
continue;
242+
}
220243
// Re-process all Bean fields and let the default swagger-jaxrs/swagger-jersey-jaxrs processors do their thing
221244
ResolvedParameter resolvedParameter = extensions.next().extractParameters(
222245
paramAnnotations,

modules/swagger-jaxrs2/src/main/java/io/swagger/v3/jaxrs2/OperationParser.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ public static Optional<RequestBody> getRequestBody(io.swagger.v3.oas.annotations
4141
if (requestBody.extensions().length > 0) {
4242
Map<String, Object> extensions = AnnotationsUtils.getExtensions(requestBody.extensions());
4343
if (extensions != null) {
44-
for (String ext : extensions.keySet()) {
45-
requestBodyObject.addExtension(ext, extensions.get(ext));
46-
}
44+
extensions.forEach(requestBodyObject::addExtension);
4745
}
4846
isEmpty = false;
4947
}
@@ -82,9 +80,7 @@ public static Optional<ApiResponses> getApiResponses(final io.swagger.v3.oas.ann
8280
if (response.extensions().length > 0) {
8381
Map<String, Object> extensions = AnnotationsUtils.getExtensions(response.extensions());
8482
if (extensions != null) {
85-
for (String ext : extensions.keySet()) {
86-
apiResponseObject.addExtension(ext, extensions.get(ext));
87-
}
83+
extensions.forEach(apiResponseObject::addExtension);
8884
}
8985
}
9086

0 commit comments

Comments
 (0)