Skip to content

GenericConversionService selects incorrect converter for String to List<String> conversion #34685

Open
@dmitrysulman

Description

@dmitrysulman

This issue is related to #34535 and #34298.

Converter<String, List<? extends Map<String, ?>>> is incorrectly selected when converting a String to a List<String>.

The following reproducer test fails on all 6.2.x versions except 6.2.3:

package com.example;

import org.junit.jupiter.api.Test;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.convert.support.StringToCollectionConverter;

import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

class GenericConversionServiceTests {

	private final GenericConversionService conversionService = new GenericConversionService();

	@Test
	@SuppressWarnings("unchecked")
	void stringToListOfString() {
		conversionService.addConverter(new StringToCollectionConverter(conversionService));
		conversionService.addConverter(new StringToListOfMapConverter());

		List<String> result = (List<String>) conversionService.convert("foo,bar",
				TypeDescriptor.valueOf(String.class),
				TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))
		);

		assertThat(result.get(0)).isEqualTo("foo");
	}

	private static class StringToListOfMapConverter implements Converter<String, List<? extends Map<String, ?>>> {

		@Override
		public List<? extends Map<String, ?>> convert(String source) {
			return List.of(Map.of("bar", source));
		}
	}

	// Using this version of the converter also results in a failure
	private static class StringToListOfMapConverterWithoutWildcard implements Converter<String, List<Map<String, ?>>> {

		@Override
		public List<Map<String, ?>> convert(String source) {
			return List.of(Map.of("bar", source));
		}
	}
}

The exception shows that the StringToListOfMapConverter converter was chosen instead of expected StringToCollectionConverter:

class java.util.ImmutableCollections$Map1 cannot be cast to class java.lang.String (java.util.ImmutableCollections$Map1 and java.lang.String are in module java.base of loader 'bootstrap')
java.lang.ClassCastException: class java.util.ImmutableCollections$Map1 cannot be cast to class java.lang.String (java.util.ImmutableCollections$Map1 and java.lang.String are in module java.base of loader 'bootstrap')
	at org.springframework.core.convert.support.GenericConversionServiceTests.stringToListOfString(GenericConversionServiceTests.java:28)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)

Activity

belljun3395

belljun3395 commented on Mar 30, 2025

@belljun3395

I think adding a few more conditions in GenericConversionService#getRegisteredConverter ConverterAdapter#matchesFallback could fix the issue.

If this is something that needs to be fixed, do you mind if I try to fix it?

added
in: coreIssues in core modules (aop, beans, core, context, expression)
on Apr 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: waiting-for-triageAn issue we've not yet triaged or decided on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @jhoeller@spring-projects-issues@dmitrysulman@belljun3395

      Issue actions

        `GenericConversionService` selects incorrect converter for `String` to `List<String>` conversion · Issue #34685 · spring-projects/spring-framework