Skip to content

Commit 1308c91

Browse files
refactor: add DiscriminatorResolver for handling discriminator properties in schemas
1 parent 4aeaa51 commit 1308c91

2 files changed

Lines changed: 81 additions & 48 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.swagger.v3.core.jackson;
2+
3+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
4+
import com.fasterxml.jackson.databind.JavaType;
5+
import io.swagger.v3.core.converter.AnnotatedType;
6+
import io.swagger.v3.core.converter.ModelConverterContext;
7+
import io.swagger.v3.core.util.AnnotationsUtils;
8+
import io.swagger.v3.oas.annotations.media.DiscriminatorMapping;
9+
import io.swagger.v3.oas.models.media.Discriminator;
10+
import io.swagger.v3.oas.models.media.JsonSchema;
11+
import io.swagger.v3.oas.models.media.Schema;
12+
import io.swagger.v3.oas.models.media.StringSchema;
13+
import org.apache.commons.lang3.StringUtils;
14+
15+
import static io.swagger.v3.core.util.RefUtils.constructRef;
16+
17+
class DiscriminatorUtils {
18+
19+
private DiscriminatorUtils() {
20+
}
21+
22+
private static final int SCHEMA_COMPONENT_PREFIX = "#/components/schemas/".length();
23+
private static final String TYPE_STRING = "string";
24+
25+
public static void resolveDiscriminatorProperty(JavaType type,
26+
ModelConverterContext context,
27+
Schema model,
28+
boolean openapi31) {
29+
// add JsonTypeInfo.property if not member of bean
30+
JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class);
31+
if (typeInfo != null) {
32+
String typeInfoProp = typeInfo.property();
33+
if (StringUtils.isNotBlank(typeInfoProp)) {
34+
Schema modelToUpdate = model;
35+
if (StringUtils.isNotBlank(model.get$ref())) {
36+
modelToUpdate = context.getDefinedModels().get(model.get$ref().substring(SCHEMA_COMPONENT_PREFIX));
37+
}
38+
if (modelToUpdate.getProperties() == null || !modelToUpdate.getProperties().keySet().contains(typeInfoProp)) {
39+
Schema discriminatorSchema = openapi31 ? new JsonSchema().typesItem(TYPE_STRING).name(typeInfoProp) : new StringSchema().name(typeInfoProp);
40+
modelToUpdate.addProperties(typeInfoProp, discriminatorSchema);
41+
if (modelToUpdate.getRequired() == null || !modelToUpdate.getRequired().contains(typeInfoProp)) {
42+
modelToUpdate.addRequiredItem(typeInfoProp);
43+
}
44+
}
45+
}
46+
}
47+
}
48+
49+
public static Discriminator resolveDiscriminator(JavaType type, ModelConverterContext context) {
50+
io.swagger.v3.oas.annotations.media.Schema declaredSchemaAnnotation = AnnotationsUtils.getSchemaDeclaredAnnotation(type.getRawClass());
51+
52+
String disc = (declaredSchemaAnnotation == null) ? "" : declaredSchemaAnnotation.discriminatorProperty();
53+
54+
if (disc.isEmpty()) {
55+
// longer method would involve AnnotationIntrospector.findTypeResolver(...) but:
56+
JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class);
57+
if (typeInfo != null) {
58+
disc = typeInfo.property();
59+
}
60+
}
61+
if (!disc.isEmpty()) {
62+
Discriminator discriminator = new Discriminator()
63+
.propertyName(disc);
64+
if (declaredSchemaAnnotation != null) {
65+
DiscriminatorMapping[] mappings = declaredSchemaAnnotation.discriminatorMapping();
66+
if (mappings != null && mappings.length > 0) {
67+
for (DiscriminatorMapping mapping : mappings) {
68+
if (!mapping.value().isEmpty() && !mapping.schema().equals(Void.class)) {
69+
discriminator.mapping(mapping.value(), constructRef(context.resolve(new AnnotatedType().type(mapping.schema())).getName()));
70+
}
71+
}
72+
}
73+
}
74+
75+
return discriminator;
76+
}
77+
return null;
78+
}
79+
}

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

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import io.swagger.v3.oas.annotations.media.DependentRequired;
4141
import io.swagger.v3.oas.annotations.media.DependentSchema;
4242
import io.swagger.v3.oas.annotations.media.DependentSchemas;
43-
import io.swagger.v3.oas.annotations.media.DiscriminatorMapping;
4443
import io.swagger.v3.oas.annotations.media.PatternProperties;
4544
import io.swagger.v3.oas.annotations.media.PatternProperty;
4645
import io.swagger.v3.oas.annotations.media.SchemaProperties;
@@ -2694,24 +2693,7 @@ protected Map<String, Object> resolveExtensions(Annotated a, Annotation[] annota
26942693
}
26952694

26962695
protected void resolveDiscriminatorProperty(JavaType type, ModelConverterContext context, Schema model) {
2697-
// add JsonTypeInfo.property if not member of bean
2698-
JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class);
2699-
if (typeInfo != null) {
2700-
String typeInfoProp = typeInfo.property();
2701-
if (StringUtils.isNotBlank(typeInfoProp)) {
2702-
Schema modelToUpdate = model;
2703-
if (StringUtils.isNotBlank(model.get$ref())) {
2704-
modelToUpdate = context.getDefinedModels().get(model.get$ref().substring(SCHEMA_COMPONENT_PREFIX));
2705-
}
2706-
if (modelToUpdate.getProperties() == null || !modelToUpdate.getProperties().keySet().contains(typeInfoProp)) {
2707-
Schema discriminatorSchema = openapi31 ? new JsonSchema().typesItem("string").name(typeInfoProp) : new StringSchema().name(typeInfoProp);
2708-
modelToUpdate.addProperties(typeInfoProp, discriminatorSchema);
2709-
if (modelToUpdate.getRequired() == null || !modelToUpdate.getRequired().contains(typeInfoProp)) {
2710-
modelToUpdate.addRequiredItem(typeInfoProp);
2711-
}
2712-
}
2713-
}
2714-
}
2696+
DiscriminatorUtils.resolveDiscriminatorProperty(type, context, model, openapi31);
27152697
}
27162698

27172699
/*
@@ -2748,35 +2730,7 @@ protected Schema resolveWrapping(JavaType type, ModelConverterContext context, S
27482730
}
27492731

27502732
protected Discriminator resolveDiscriminator(JavaType type, ModelConverterContext context) {
2751-
2752-
io.swagger.v3.oas.annotations.media.Schema declaredSchemaAnnotation = AnnotationsUtils.getSchemaDeclaredAnnotation(type.getRawClass());
2753-
2754-
String disc = (declaredSchemaAnnotation == null) ? "" : declaredSchemaAnnotation.discriminatorProperty();
2755-
2756-
if (disc.isEmpty()) {
2757-
// longer method would involve AnnotationIntrospector.findTypeResolver(...) but:
2758-
JsonTypeInfo typeInfo = type.getRawClass().getDeclaredAnnotation(JsonTypeInfo.class);
2759-
if (typeInfo != null) {
2760-
disc = typeInfo.property();
2761-
}
2762-
}
2763-
if (!disc.isEmpty()) {
2764-
Discriminator discriminator = new Discriminator()
2765-
.propertyName(disc);
2766-
if (declaredSchemaAnnotation != null) {
2767-
DiscriminatorMapping[] mappings = declaredSchemaAnnotation.discriminatorMapping();
2768-
if (mappings != null && mappings.length > 0) {
2769-
for (DiscriminatorMapping mapping : mappings) {
2770-
if (!mapping.value().isEmpty() && !mapping.schema().equals(Void.class)) {
2771-
discriminator.mapping(mapping.value(), constructRef(context.resolve(new AnnotatedType().type(mapping.schema())).getName()));
2772-
}
2773-
}
2774-
}
2775-
}
2776-
2777-
return discriminator;
2778-
}
2779-
return null;
2733+
return DiscriminatorUtils.resolveDiscriminator(type, context);
27802734
}
27812735

27822736
protected XML resolveXml(Annotated a, Annotation[] annotations, io.swagger.v3.oas.annotations.media.Schema schema) {

0 commit comments

Comments
 (0)