Skip to content

Commit 0b467f3

Browse files
committed
fix: prevent leaking properties to enum schema when Schema#implementation is set. Fixes: #4800
1 parent 5e0bb63 commit 0b467f3

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -751,10 +751,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
751751

752752
Annotation[] ctxAnnotation31 = null;
753753
Schema.SchemaResolution resolvedSchemaResolution = AnnotationsUtils.resolveSchemaResolution(this.schemaResolution, ctxSchema);
754-
if (
755-
Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) ||
756-
Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) ||
757-
openapi31) {
754+
if (AnnotationsUtils.areSiblingsAllowed(resolvedSchemaResolution, openapi31)) {
758755
List<Annotation> ctxAnnotations31List = new ArrayList<>();
759756
if (annotations != null) {
760757
for (Annotation a : annotations) {
@@ -763,9 +760,6 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
763760
!(a instanceof io.swagger.v3.oas.annotations.media.ArraySchema)) {
764761
ctxAnnotations31List.add(a);
765762
}
766-
if ((ctxSchema != null) && (!ctxSchema.implementation().equals(Void.class) || StringUtils.isNotEmpty(ctxSchema.type()))) {
767-
ctxAnnotations31List.add(a);
768-
}
769763
}
770764
ctxAnnotation31 = ctxAnnotations31List.toArray(new Annotation[ctxAnnotations31List.size()]);
771765
}
@@ -823,6 +817,9 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
823817
return openapi31 ? new JsonSchema() : new Schema();
824818
}
825819
});
820+
821+
boolean areSiblingsAllowed = AnnotationsUtils.areSiblingsAllowed(resolvedSchemaResolution, openapi31);
822+
aType = AnnotationsUtils.addTypeWhenSiblingsAllowed(aType, ctxSchema, areSiblingsAllowed);
826823
property = context.resolve(aType);
827824
property = clone(property);
828825
Schema ctxProperty = null;

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2916,4 +2916,19 @@ public static boolean computeEnumAsRef(io.swagger.v3.oas.annotations.media.Schem
29162916
}
29172917
return false;
29182918
}
2919+
2920+
public static boolean areSiblingsAllowed(Schema.SchemaResolution resolvedSchemaResolution, boolean openapi31) {
2921+
return Schema.SchemaResolution.ALL_OF.equals(resolvedSchemaResolution) || Schema.SchemaResolution.ALL_OF_REF.equals(resolvedSchemaResolution) || openapi31;
2922+
}
2923+
2924+
public static AnnotatedType addTypeWhenSiblingsAllowed(AnnotatedType aType, io.swagger.v3.oas.annotations.media.Schema ctxSchema, boolean areSiblingsAllowed) {
2925+
if (areSiblingsAllowed && ctxSchema != null) {
2926+
if (!Void.class.equals(ctxSchema.implementation())) {
2927+
aType.setType(ctxSchema.implementation());
2928+
} else if (StringUtils.isNotBlank(ctxSchema.type())) {
2929+
aType.setType(ctxSchema.type().getClass());
2930+
}
2931+
}
2932+
return aType;
2933+
}
29192934
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.swagger.v3.core.resolving;
2+
3+
import io.swagger.v3.core.converter.ModelConverters;
4+
import io.swagger.v3.core.matchers.SerializationMatchers;
5+
import io.swagger.v3.oas.models.media.Schema;
6+
import org.testng.annotations.Test;
7+
8+
import java.util.Map;
9+
10+
public class Ticket4800Test extends SwaggerTestBase{
11+
12+
@Test(description = "Custom schema implementation in property and enum as ref type value")
13+
public void testCustomSchemaImplementation() {
14+
15+
String expectedYaml = "ModelWithCustomSchemaImplementationInProperty:\n" +
16+
" type: object\n" +
17+
" properties:\n" +
18+
" enumExampleFieldWithImplementationProp:\n" +
19+
" $ref: \"#/components/schemas/MyEnum\"\n" +
20+
" default: \"yes\"\n" +
21+
" description: Prop description\n" +
22+
" secondExampleFieldWithTypeProp:\n" +
23+
" type: string\n" +
24+
"MyEnum:\n" +
25+
" type: string\n" +
26+
" enum:\n" +
27+
" - \"yes\"\n" +
28+
" - \"no\"";
29+
30+
Map<String, Schema> stringSchemaMap = ModelConverters.getInstance(true).readAll(Ticket4800Test.ModelWithCustomSchemaImplementationInProperty.class);
31+
SerializationMatchers.assertEqualsToYaml31(stringSchemaMap, expectedYaml);
32+
}
33+
34+
static class ModelWithCustomSchemaImplementationInProperty {
35+
36+
@io.swagger.v3.oas.annotations.media.Schema(implementation = MyEnum.class, description = "Prop description", defaultValue = "yes", enumAsRef = true)
37+
private MyEnum enumExampleFieldWithImplementationProp;
38+
39+
@io.swagger.v3.oas.annotations.media.Schema(type = "string", enumAsRef = true)
40+
private MyEnum2 secondExampleFieldWithTypeProp;
41+
42+
public MyEnum getEnumExampleFieldWithImplementationProp() {
43+
return enumExampleFieldWithImplementationProp;
44+
}
45+
46+
public void setEnumExampleFieldWithImplementationProp(MyEnum enumExampleFieldWithImplementationProp) {
47+
this.enumExampleFieldWithImplementationProp = enumExampleFieldWithImplementationProp;
48+
}
49+
50+
public MyEnum2 getSecondExampleFieldWithTypeProp() {
51+
return secondExampleFieldWithTypeProp;
52+
}
53+
54+
public void setSecondExampleFieldWithTypeProp(MyEnum2 secondExampleFieldWithTypeProp) {
55+
this.secondExampleFieldWithTypeProp = secondExampleFieldWithTypeProp;
56+
}
57+
58+
enum MyEnum {
59+
yes, no
60+
}
61+
62+
//Should not be included in the model definitions
63+
enum MyEnum2 {
64+
si, no
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)