Skip to content

Commit 4d942c8

Browse files
Improve EnumSet handling in MappingRedisConverter.
Add special handling of EnumSet, extracting the value type hint from the source to create the instance. See: #3179
1 parent f3f4436 commit 4d942c8

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,15 @@ public void write(@Nullable Object source, RedisData sink) {
409409
if (collection instanceof List) {
410410
collectionTargetType = List.class;
411411
} else if (collection instanceof Set) {
412-
collectionTargetType = collection instanceof EnumSet ? EnumSet.class : Set.class;
412+
if (collection instanceof EnumSet<?>) {
413+
collectionTargetType = EnumSet.class;
414+
} else {
415+
collectionTargetType = Set.class;
416+
}
413417
}
418+
414419
typeMapper.writeType(collectionTargetType, sink.getBucket().getPath());
415-
writeCollection(sink.getKeyspace(), "", collection, TypeInformation.of(Object.class), sink);
420+
writeCollection(sink.getKeyspace(), "", collection, TypeInformation.OBJECT, sink);
416421
return;
417422
}
418423

@@ -829,7 +834,13 @@ private void writeToBucket(String path, @Nullable Object value, RedisData sink,
829834

830835
boolean isArray = collectionType.isArray();
831836
Class<?> collectionTypeToUse = isArray ? ArrayList.class : collectionType;
832-
Collection<Object> target = CollectionFactory.createCollection(collectionTypeToUse, valueType, keys.size());
837+
Class<?> valueTypeToUse = valueType;
838+
839+
if (collectionTypeToUse == EnumSet.class) {
840+
valueTypeToUse = findFirstElementType(bucket, keys, valueType);
841+
}
842+
843+
Collection<Object> target = CollectionFactory.createCollection(collectionTypeToUse, valueTypeToUse, keys.size());
833844

834845
for (String key : keys) {
835846

@@ -977,6 +988,17 @@ private void writeMap(@Nullable String keyspace, String path, Class<?> mapValueT
977988
return conversionService.convert(toBytes(mapKey), targetType);
978989
}
979990

991+
private Class<?> findFirstElementType(Bucket bucket, List<String> keys, Class<?> fallbackType) {
992+
993+
Optional<String> firstElement = keys.stream().filter(typeMapper::isTypeKey)
994+
.map(it -> it.substring(0, it.indexOf(']') + 1)).findFirst();
995+
if (firstElement.isEmpty()) {
996+
return fallbackType;
997+
}
998+
999+
return getTypeHint(firstElement.get(), bucket, fallbackType);
1000+
}
1001+
9801002
private Class<?> getTypeHint(String path, Bucket bucket, Class<?> fallback) {
9811003

9821004
TypeInformation<?> typeInformation = typeMapper.readType(bucket.getPropertyPath(path),

src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.util.Collection;
6060
import java.util.Collections;
6161
import java.util.Date;
62+
import java.util.EnumSet;
6263
import java.util.HashMap;
6364
import java.util.LinkedHashMap;
6465
import java.util.List;
@@ -2044,11 +2045,14 @@ void readsPlainCollectionIfObjectTypeRequested(Class<?> type, Collection<Object>
20442045

20452046
Object target = this.converter.read(Object.class, source.getRedisData());
20462047

2047-
assertThat(target).isInstanceOf(type).asInstanceOf(InstanceOfAssertFactories.COLLECTION).containsExactlyElementsOf(collection);
2048+
assertThat(target).isInstanceOf(type).asInstanceOf(InstanceOfAssertFactories.COLLECTION)
2049+
.containsExactlyElementsOf(collection);
20482050
}
20492051

20502052
private static Stream<Arguments> justCollections() {
2051-
return Stream.of(Arguments.of(List.class, Arrays.asList("Hello", "stream", "message", 100L)), Arguments.of(Set.class, Set.of("Hello", "stream", "message", 100L)));
2053+
return Stream.of(Arguments.of(List.class, Arrays.asList("Hello", "stream", "message", 100L)),
2054+
Arguments.of(Set.class, Set.of("Hello", "stream", "message", 100L)),
2055+
Arguments.of(EnumSet.class, EnumSet.allOf(Gender.class)));
20522056
}
20532057

20542058
private RedisTestData write(Object source) {

0 commit comments

Comments
 (0)