Merge branch '7.0.x'

This commit is contained in:
Sam Brannen
2026-09-08 13:30:50 +02:00
4 changed files with 45 additions and 7 deletions
@@ -22,7 +22,6 @@ import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -71,12 +70,17 @@ abstract class ConversionUtils {
return false;
}
public static Class<?> getEnumType(Class<?> targetType) {
/**
* Resolve the enum type for the supplied target type.
* @param targetType the target type for which to resolve the enum type
* @return the resolved enum type, or {@code null} if the supplied target type
* does not refer to an enum
*/
public static @Nullable Class<?> resolveEnumType(Class<?> targetType) {
Class<?> enumType = targetType;
while (enumType != null && !enumType.isEnum()) {
enumType = enumType.getSuperclass();
}
Assert.notNull(enumType, () -> "The target type " + targetType.getName() + " does not refer to an enum");
return enumType;
}
@@ -18,8 +18,11 @@ package org.springframework.core.convert.support;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalConverter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.Assert;
/**
* Converts from an Integer to a {@link java.lang.Enum} by calling {@link Class#getEnumConstants()}.
@@ -29,11 +32,18 @@ import org.springframework.core.convert.converter.ConverterFactory;
* @since 4.3
*/
@SuppressWarnings({"rawtypes", "unchecked"})
final class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum> {
final class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum>, ConditionalConverter {
@Override
public <T extends Enum> Converter<Integer, @Nullable T> getConverter(Class<T> targetType) {
return new IntegerToEnum(ConversionUtils.getEnumType(targetType));
Class<?> enumType = ConversionUtils.resolveEnumType(targetType);
Assert.notNull(enumType, () -> "The target type " + targetType.getName() + " does not refer to an enum");
return new IntegerToEnum(enumType);
}
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return (ConversionUtils.resolveEnumType(targetType.getType()) != null);
}
@@ -18,8 +18,11 @@ package org.springframework.core.convert.support;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalConverter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.Assert;
/**
* Converts from a String to a {@link java.lang.Enum} by calling {@link Enum#valueOf(Class, String)}.
@@ -29,11 +32,18 @@ import org.springframework.core.convert.converter.ConverterFactory;
* @since 3.0
*/
@SuppressWarnings({"rawtypes", "unchecked"})
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum>, ConditionalConverter {
@Override
public <T extends Enum> Converter<String, @Nullable T> getConverter(Class<T> targetType) {
return new StringToEnum(ConversionUtils.getEnumType(targetType));
Class<?> enumType = ConversionUtils.resolveEnumType(targetType);
Assert.notNull(enumType, () -> "The target type " + targetType.getName() + " does not refer to an enum");
return new StringToEnum(enumType);
}
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return (ConversionUtils.resolveEnumType(targetType.getType()) != null);
}
@@ -503,6 +503,20 @@ class GenericConversionServiceTests {
assertThat(conversionService.convert("base1", MyEnum.class)).isEqualTo(MyEnum.A);
}
@Test // gh-34532
void canConvertToEnumDoesNotThrowForNonEnumTargetType() {
conversionService.addConverterFactory(new StringToEnumConverterFactory());
conversionService.addConverterFactory(new IntegerToEnumConverterFactory());
assertThat(conversionService.canConvert(String.class, Enum.class)).isFalse();
assertThat(conversionService.canConvert(Integer.class, Enum.class)).isFalse();
assertThat(conversionService.canConvert(String.class, MyEnum.class)).isTrue();
assertThat(conversionService.canConvert(Integer.class, MyEnum.class)).isTrue();
assertThat(conversionService.convert("A", MyEnum.class)).isEqualTo(MyEnum.A);
assertThat(conversionService.convert(0, MyEnum.class)).isEqualTo(MyEnum.A);
}
@Test
void convertNullAnnotatedStringToString() throws Exception {
String source = null;