Fix CustomConverter conversion lookup.
This commit makes sure to fall back to the configured custom converter if no more type specific converter has been registered. Closes #3580 Original pull request: #3581.
This commit is contained in:
committed by
Mark Paluch
parent
a88748d798
commit
a1a0675976
@@ -292,7 +292,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Class<? extends S> rawType = typeToRead.getType();
|
||||
|
||||
if (conversions.hasCustomReadTarget(bson.getClass(), rawType)) {
|
||||
return doConvert(bson, rawType);
|
||||
return doConvert(bson, rawType, typeHint.getType());
|
||||
}
|
||||
|
||||
if (Document.class.isAssignableFrom(rawType)) {
|
||||
@@ -1532,9 +1532,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return target;
|
||||
}
|
||||
|
||||
private <T extends Object> T doConvert(Object value, Class<? extends T> target) {
|
||||
return doConvert(value, target, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private <T> T doConvert(Object value, Class<T> target) {
|
||||
return conversionService.convert(value, target);
|
||||
private <T extends Object> T doConvert(Object value, Class<? extends T> target, @Nullable Class<? extends T> fallback) {
|
||||
|
||||
if(conversionService.canConvert(value.getClass(), target) || fallback == null) {
|
||||
return conversionService.convert(value, target);
|
||||
}
|
||||
return conversionService.convert(value, fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2383,6 +2383,51 @@ class MappingMongoConverterUnitTests {
|
||||
.doesNotContainKey("address.city");
|
||||
}
|
||||
|
||||
@Test // GH-3580
|
||||
void shouldFallbackToConfiguredCustomConversionTargetOnRead() {
|
||||
|
||||
GenericTypeConverter genericTypeConverter = spy(new GenericTypeConverter());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(MongoCustomConversions.create(it -> {
|
||||
it.registerConverter(genericTypeConverter);
|
||||
}));
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
org.bson.Document source = new org.bson.Document("_class", SubTypeOfGenericType.class.getName()).append("value",
|
||||
"v1");
|
||||
GenericType target = converter.read(GenericType.class, source);
|
||||
|
||||
assertThat(target).isInstanceOf(GenericType.class);
|
||||
assertThat(target.content).isEqualTo("v1");
|
||||
|
||||
verify(genericTypeConverter).convert(eq(source));
|
||||
}
|
||||
|
||||
@Test // GH-3580
|
||||
void shouldUseMostConcreteCustomConversionTargetOnRead() {
|
||||
|
||||
GenericTypeConverter genericTypeConverter = spy(new GenericTypeConverter());
|
||||
SubTypeOfGenericTypeConverter subTypeOfGenericTypeConverter = spy(new SubTypeOfGenericTypeConverter());
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(MongoCustomConversions.create(it -> {
|
||||
it.registerConverter(genericTypeConverter);
|
||||
it.registerConverter(subTypeOfGenericTypeConverter);
|
||||
}));
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
org.bson.Document source = new org.bson.Document("_class", SubTypeOfGenericType.class.getName()).append("value",
|
||||
"v1");
|
||||
GenericType target = converter.read(GenericType.class, source);
|
||||
|
||||
assertThat(target).isInstanceOf(SubTypeOfGenericType.class);
|
||||
assertThat(target.content).isEqualTo("v1_s");
|
||||
|
||||
verify(genericTypeConverter, never()).convert(any());
|
||||
verify(subTypeOfGenericTypeConverter).convert(eq(source));
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -2899,4 +2944,31 @@ class MappingMongoConverterUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
static class SubTypeOfGenericType extends GenericType<String> {
|
||||
|
||||
}
|
||||
|
||||
@ReadingConverter
|
||||
static class GenericTypeConverter implements Converter<org.bson.Document, GenericType<?>> {
|
||||
|
||||
@Override
|
||||
public GenericType<?> convert(org.bson.Document source) {
|
||||
|
||||
GenericType<Object> target = new GenericType<>();
|
||||
target.content = source.get("value");
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@ReadingConverter
|
||||
static class SubTypeOfGenericTypeConverter implements Converter<org.bson.Document, SubTypeOfGenericType> {
|
||||
|
||||
@Override
|
||||
public SubTypeOfGenericType convert(org.bson.Document source) {
|
||||
|
||||
SubTypeOfGenericType target = new SubTypeOfGenericType();
|
||||
target.content = source.getString("value") + "_s";
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user