Consider custom converters in ConversionContext before applying collection converters.
We now inspect whether custom conversions should be applied before reading a value into a Map or Collection to consider converters for Map-like and Collection-like types. Closes #1181
This commit is contained in:
@@ -144,7 +144,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
*/
|
||||
protected ConversionContext getConversionContext() {
|
||||
|
||||
return new ConversionContext(this::doReadRow, this::doReadTupleValue, this::doReadUdtValue,
|
||||
return new ConversionContext(getCustomConversions(), this::doReadRow, this::doReadTupleValue, this::doReadUdtValue,
|
||||
this::readCollectionOrArray, this::readMap, this::getPotentiallyConvertedSimpleRead);
|
||||
}
|
||||
|
||||
@@ -1161,6 +1161,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
*/
|
||||
protected static class ConversionContext {
|
||||
|
||||
private final org.springframework.data.convert.CustomConversions conversions;
|
||||
|
||||
private final ContainerValueConverter<Row> rowConverter;
|
||||
|
||||
private final ContainerValueConverter<TupleValue> tupleConverter;
|
||||
@@ -1173,10 +1175,12 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
private final ValueConverter<Object> elementConverter;
|
||||
|
||||
public ConversionContext(ContainerValueConverter<Row> rowConverter,
|
||||
public ConversionContext(org.springframework.data.convert.CustomConversions conversions,
|
||||
ContainerValueConverter<Row> rowConverter,
|
||||
ContainerValueConverter<TupleValue> tupleConverter, ContainerValueConverter<UdtValue> udtConverter,
|
||||
ContainerValueConverter<Collection<?>> collectionConverter, ContainerValueConverter<Map<?, ?>> mapConverter,
|
||||
ValueConverter<Object> elementConverter) {
|
||||
this.conversions = conversions;
|
||||
this.rowConverter = rowConverter;
|
||||
this.tupleConverter = tupleConverter;
|
||||
this.udtConverter = udtConverter;
|
||||
@@ -1197,6 +1201,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
|
||||
Assert.notNull(typeHint, "TypeInformation must not be null");
|
||||
|
||||
if (conversions.hasCustomReadTarget(source.getClass(), typeHint.getType())) {
|
||||
return (S) elementConverter.convert(source, typeHint);
|
||||
}
|
||||
|
||||
if (source instanceof Collection) {
|
||||
|
||||
Class<?> rawType = typeHint.getType();
|
||||
|
||||
@@ -38,10 +38,14 @@ import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.*;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
@@ -1445,4 +1449,53 @@ public class MappingCassandraConverterUnitTests {
|
||||
WithNullableEmbeddedType target = mappingCassandraConverter.read(WithNullableEmbeddedType.class, source);
|
||||
assertThat(target.nested).isNull();
|
||||
}
|
||||
|
||||
@Test // DATACASS-1181
|
||||
void shouldApplyCustomConverterToMapLikeType() {
|
||||
|
||||
CassandraCustomConversions conversions = new CassandraCustomConversions(
|
||||
Arrays.asList(JsonToStringConverter.INSTANCE, StringToJsonConverter.INSTANCE));
|
||||
|
||||
this.mappingContext = new CassandraMappingContext();
|
||||
this.mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
|
||||
this.mappingCassandraConverter = new MappingCassandraConverter(mappingContext);
|
||||
this.mappingCassandraConverter.setCustomConversions(conversions);
|
||||
this.mappingCassandraConverter.afterPropertiesSet();
|
||||
|
||||
Row source = RowMockUtil.newRowMock(column("thejson", "{\"hello\":\"world\"}", DataTypes.TEXT));
|
||||
|
||||
TypeWithJsonObject target = mappingCassandraConverter.read(TypeWithJsonObject.class, source);
|
||||
assertThat(target.theJson).isNotNull();
|
||||
assertThat(target.theJson.get("hello")).isEqualTo("world");
|
||||
}
|
||||
|
||||
static class TypeWithJsonObject {
|
||||
|
||||
JSONObject theJson;
|
||||
}
|
||||
|
||||
enum StringToJsonConverter implements Converter<String, JSONObject> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public JSONObject convert(String source) {
|
||||
try {
|
||||
return (JSONObject) new JSONParser().parse(source);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum JsonToStringConverter implements Converter<JSONObject, String> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(JSONObject source) {
|
||||
return source.toJSONString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user