Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ private static void collectAnnotatedMethodsFromInterfaces(Class<?> type, Class<?

private static void collectAnnotatedDeclaredMethods(Class<?> cls, Class<? extends Annotation> annotation, List<Method> methods) {
for (Method method : cls.getDeclaredMethods()) {
if (method.isAnnotationPresent(annotation)) {
if (!method.isBridge() && method.isAnnotationPresent(annotation)) {
methods.add(method);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.core.jackson.TypeNameResolver;
import io.swagger.v3.core.matchers.SerializationMatchers;
import io.swagger.v3.core.oas.models.JacksonValueBridgeMethodEnum;
import io.swagger.v3.core.oas.models.JacksonValueDefaultMethodEnum;
import io.swagger.v3.core.oas.models.JacksonValuePrivateEnum;
import io.swagger.v3.core.oas.models.Model1979;
Expand Down Expand Up @@ -266,4 +267,12 @@ public void testJsonValueOnInterfaceDefaultMethodIsRecognized() {
assertEquals(schema.getType(), "string");
assertEquals(schema.getEnum(), Arrays.asList("alpha", "beta", "gamma"));
}

@Test(description = "it should handle @JsonValue on enum implementing generic interface with bridge method (issue #5127)")
public void testJsonValueWithBridgeMethodFromGenericInterface() {
final Schema schema = context.resolve(new AnnotatedType(JacksonValueBridgeMethodEnum.class));
assertNotNull(schema);
assertEquals(schema.getType(), "string");
assertEquals(schema.getEnum(), Arrays.asList("created", "in_progress", "confirmed"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.swagger.v3.core.oas.models;

import com.fasterxml.jackson.annotation.JsonValue;

/**
* Enum implementing a generic interface, causing the compiler to generate a bridge
* method {@code Object getValue()} alongside the real {@code String getValue()}.
* The {@code @JsonValue} annotation is present on the real method, but the compiler
* may copy it to the bridge method as well. This tests that the bridge method does
* not interfere with schema type detection.
*
* @see <a href="https://github.com/swagger-api/swagger-core/issues/5127">Issue #5127</a>
*/
public enum JacksonValueBridgeMethodEnum implements PersistableEnum<String> {
CREATED("created"),
IN_PROGRESS("in_progress"),
CONFIRMED("confirmed");

private final String value;

JacksonValueBridgeMethodEnum(String value) {
this.value = value;
}

@JsonValue
@Override
public String getValue() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.swagger.v3.core.oas.models;

/**
* Generic interface whose {@code getValue()} method causes the compiler to generate
* a bridge method on implementing enums. Used to test that bridge methods do not
* interfere with {@code @JsonValue} detection.
*/
public interface PersistableEnum<T> {
T getValue();
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,31 @@ public void getAnnotatedMethods_findsDefaultMethodAnnotationFromInterface() {
assertEquals(methods.get(0).getName(), "toValue");
}

@Test
public void getAnnotatedMethods_excludesBridgeMethodsFromGenericInterface() {
// GenericValueEnum implements PersistableEnum<String> which causes the compiler
// to generate a bridge method Object getValue() alongside String getValue().
// Both may carry @JsonValue, but only the non-bridge method should be returned.
List<Method> methods = ReflectionUtils.getAnnotatedMethods(GenericValueEnum.class, JsonValue.class);
assertEquals(methods.size(), 1, "should find exactly one @JsonValue method (excluding bridge)");
assertEquals(methods.get(0).getReturnType(), String.class, "should find the String-returning method, not the Object bridge");
}

// --- Support classes for getAnnotatedMethods tests ---

private interface GenericPersistableEnum<T> {
T getValue();
}

private enum GenericValueEnum implements GenericPersistableEnum<String> {
A("alpha"), B("beta");
private final String value;
GenericValueEnum(String value) { this.value = value; }
@JsonValue
@Override
public String getValue() { return value; }
}

private static class SuperclassWithJsonValue {
@JsonValue
public String getJsonValue() { return "super"; }
Expand Down