diff --git a/core/src/main/java/io/smallrye/openapi/runtime/scanner/dataobject/TypeResolver.java b/core/src/main/java/io/smallrye/openapi/runtime/scanner/dataobject/TypeResolver.java index 63b8d6460..006e8dacf 100644 --- a/core/src/main/java/io/smallrye/openapi/runtime/scanner/dataobject/TypeResolver.java +++ b/core/src/main/java/io/smallrye/openapi/runtime/scanner/dataobject/TypeResolver.java @@ -1148,11 +1148,30 @@ private static boolean isHigherPriority(Comparator targetCompa private static UnaryOperator getPropertyNameTranslator(AnnotationScannerContext context, AnnotationTarget target) { ClassInfo clazz = target.kind() == Kind.CLASS ? target.asClass() : TypeUtil.getDeclaringClass(target); - AnnotationInstance jacksonNaming = context.annotations().getAnnotation(clazz, JacksonConstants.JSON_NAMING); + AugmentedIndexView index = context.getAugmentedIndex(); + Map chain = index.inheritanceChain(clazz, Type.create(clazz.name(), Type.Kind.CLASS)); + Annotations annotations = context.annotations(); + AnnotationInstance jacksonNaming = null; + + for (ClassInfo entry : chain.keySet()) { + jacksonNaming = annotations.getAnnotation(entry, JacksonConstants.JSON_NAMING); + + if (jacksonNaming == null) { + jacksonNaming = index.interfaces(entry) + .stream() + .map(index::getClass) + .filter(Objects::nonNull) + .map(interfaceClass -> annotations.getAnnotation(interfaceClass, JacksonConstants.JSON_NAMING)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + } + UnaryOperator translator; if (jacksonNaming != null) { - Type namingClass = context.annotations().value(jacksonNaming, JacksonConstants.PROP_VALUE); + Type namingClass = annotations.value(jacksonNaming, JacksonConstants.PROP_VALUE); if (namingClass != null) { translator = PropertyNamingStrategyFactory.getStrategy(namingClass.name().toString(), context.getClassLoader()); diff --git a/core/src/test/java/io/smallrye/openapi/runtime/scanner/PropertyNamingStrategyTest.java b/core/src/test/java/io/smallrye/openapi/runtime/scanner/PropertyNamingStrategyTest.java index 667ce4333..43e86785e 100644 --- a/core/src/test/java/io/smallrye/openapi/runtime/scanner/PropertyNamingStrategyTest.java +++ b/core/src/test/java/io/smallrye/openapi/runtime/scanner/PropertyNamingStrategyTest.java @@ -11,6 +11,7 @@ import java.util.Map; import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.models.OpenAPI; import org.junit.jupiter.api.Test; @@ -194,4 +195,26 @@ public String translate(String value) { throw new IllegalArgumentException("dummy"); } } + + @JsonNaming(com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy.class) + @Schema(discriminatorProperty = "type", discriminatorMapping = { + @DiscriminatorMapping(value = "bird", schema = Bird.class), + @DiscriminatorMapping(value = "dog", schema = Dog.class), + }) + interface Animal { + } + + static class Bird implements Animal { + String favoriteSong; + } + + static class Dog implements Animal { + String favoriteBall; + } + + @Test + void testJacksonNamingInherited() throws Exception { + OpenAPI result = scan(Animal.class, Bird.class, Dog.class); + assertJsonEquals("components.schemas.name-strategy-inherited.json", result); + } } diff --git a/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.name-strategy-inherited.json b/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.name-strategy-inherited.json new file mode 100644 index 000000000..28fb07226 --- /dev/null +++ b/core/src/test/resources/io/smallrye/openapi/runtime/scanner/components.schemas.name-strategy-inherited.json @@ -0,0 +1,33 @@ +{ + "openapi" : "3.1.0", + "components" : { + "schemas" : { + "Animal" : { + "discriminator" : { + "propertyName" : "type", + "mapping" : { + "bird" : "#/components/schemas/Bird", + "dog" : "#/components/schemas/Dog" + } + }, + "type" : "object" + }, + "Bird" : { + "type" : "object", + "properties" : { + "favorite_song" : { + "type" : "string" + } + } + }, + "Dog" : { + "type" : "object", + "properties" : { + "favorite_ball" : { + "type" : "string" + } + } + } + } + } +}