Skip to content

Commit 2472126

Browse files
committed
Add fallback to pre-6.2.3 behavior for unresolvable generics
Closes gh-34535
1 parent f3b50c9 commit 2472126

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java

+15
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
348348
conditionalConverter.matches(sourceType, targetType);
349349
}
350350

351+
public boolean matchesFallback(TypeDescriptor sourceType, TypeDescriptor targetType) {
352+
return (this.typeInfo.getTargetType() == targetType.getObjectType() &&
353+
this.targetType.hasUnresolvableGenerics() &&
354+
(!(this.converter instanceof ConditionalConverter conditionalConverter) ||
355+
conditionalConverter.matches(sourceType, targetType)));
356+
}
357+
351358
@Override
352359
@Nullable
353360
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
@@ -622,12 +629,20 @@ public void add(GenericConverter converter) {
622629

623630
@Nullable
624631
public GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
632+
// Look for proper match among all converters (taking full generics into account)
625633
for (GenericConverter converter : this.converters) {
626634
if (!(converter instanceof ConditionalGenericConverter genericConverter) ||
627635
genericConverter.matches(sourceType, targetType)) {
628636
return converter;
629637
}
630638
}
639+
// Fallback to pre-6.2.3 behavior: accept Class match for unresolvable generics
640+
for (GenericConverter converter : this.converters) {
641+
if (converter instanceof ConverterAdapter converterAdapter &&
642+
converterAdapter.matchesFallback(sourceType, targetType)) {
643+
return converter;
644+
}
645+
}
631646
return null;
632647
}
633648

spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java

+21
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,18 @@ void stringListToListOfSubclassOfUnboundGenericClass() {
581581
assertThat(bList).allMatch(e -> e instanceof BRaw);
582582
}
583583

584+
@Test
585+
void stringToListOfMapConverterWithFallbackMatch() {
586+
conversionService.addConverter(new StringToListOfMapConverter());
587+
588+
List<Map<String, Object>> result = (List<Map<String, Object>>) conversionService.convert("foo",
589+
TypeDescriptor.valueOf(String.class),
590+
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Map.class))
591+
);
592+
593+
assertThat("foo").isEqualTo(result.get(0).get("bar"));
594+
}
595+
584596

585597
@ExampleAnnotation(active = true)
586598
public String annotatedString;
@@ -971,4 +983,13 @@ public List<BRaw> convert(List<String> source) {
971983
}
972984
}
973985

986+
987+
private static class StringToListOfMapConverter implements Converter<String, List<? extends Map<String, ?>>> {
988+
989+
@Override
990+
public List<? extends Map<String, ?>> convert(String source) {
991+
return List.of(Map.of("bar", source));
992+
}
993+
}
994+
974995
}

0 commit comments

Comments
 (0)