Skip to content

Commit 872cd77

Browse files
committed
DATAREDIS-492 - Handle serializing arrays and collections
1 parent b645d37 commit 872cd77

File tree

3 files changed

+92
-8
lines changed

3 files changed

+92
-8
lines changed

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.redis.core.convert;
1717

1818
import java.util.ArrayList;
19+
import java.util.Arrays;
1920
import java.util.Collection;
2021
import java.util.Comparator;
2122
import java.util.HashMap;
@@ -354,8 +355,8 @@ public void write(Object source, final RedisData sink) {
354355
sink.setTimeToLive(ttl);
355356
}
356357

357-
for (IndexedData indexeData : indexResolver.resolveIndexesFor(entity.getTypeInformation(), source)) {
358-
sink.addIndexedData(indexeData);
358+
for (IndexedData indexedData : indexResolver.resolveIndexesFor(entity.getTypeInformation(), source)) {
359+
sink.addIndexedData(indexedData);
359360
}
360361

361362
}
@@ -408,8 +409,22 @@ public void doWithPersistentProperty(KeyValuePersistentProperty persistentProper
408409
writeMap(keyspace, propertyStringPath, persistentProperty.getMapValueType(),
409410
(Map<?, ?>) accessor.getProperty(persistentProperty), sink);
410411
} else if (persistentProperty.isCollectionLike()) {
411-
writeCollection(keyspace, propertyStringPath, (Collection<?>) accessor.getProperty(persistentProperty),
412+
413+
final Object property = accessor.getProperty(persistentProperty);
414+
415+
if (property == null || Iterable.class.isAssignableFrom(property.getClass())) {
416+
417+
writeCollection(keyspace, propertyStringPath, (Iterable<?>) property,
412418
persistentProperty.getTypeInformation().getComponentType(), sink);
419+
} else if (property.getClass().isArray()) {
420+
421+
writeCollection(keyspace, propertyStringPath, Arrays.asList((Object[]) property),
422+
persistentProperty.getTypeInformation().getComponentType(), sink);
423+
} else {
424+
425+
throw new RuntimeException("Don't know how to handle " + property.getClass() + " type collection");
426+
}
427+
413428
} else if (persistentProperty.isEntity()) {
414429
writeInternal(keyspace, propertyStringPath, accessor.getProperty(persistentProperty),
415430
persistentProperty.getTypeInformation().getActualType(), sink);
@@ -481,7 +496,7 @@ public void doWithAssociation(Association<KeyValuePersistentProperty> associatio
481496
* @param typeHint
482497
* @param sink
483498
*/
484-
private void writeCollection(String keyspace, String path, Collection<?> values, TypeInformation<?> typeHint,
499+
private void writeCollection(String keyspace, String path, Iterable<?> values, TypeInformation<?> typeHint,
485500
RedisData sink) {
486501

487502
if (values == null) {
@@ -491,6 +506,10 @@ private void writeCollection(String keyspace, String path, Collection<?> values,
491506
int i = 0;
492507
for (Object value : values) {
493508

509+
if (value == null) {
510+
break;
511+
}
512+
494513
String currentPath = path + ".[" + i + "]";
495514

496515
if (customConversions.hasCustomWriteTarget(value.getClass())) {

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
*/
1616
package org.springframework.data.redis.core.convert;
1717

18+
import java.util.Arrays;
1819
import java.util.Collections;
1920
import java.util.LinkedHashSet;
21+
import java.util.List;
2022
import java.util.Map;
2123
import java.util.Map.Entry;
2224
import java.util.Set;
@@ -116,11 +118,23 @@ public void doWithPersistentProperty(KeyValuePersistentProperty persistentProper
116118

117119
} else if (persistentProperty.isCollectionLike()) {
118120

119-
for (Object listValue : (Iterable<?>) propertyValue) {
121+
final Iterable<?> iterable;
120122

121-
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, listValue);
122-
indexes.addAll(
123+
if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
124+
iterable = (Iterable) propertyValue;
125+
} else if (propertyValue.getClass().isArray()) {
126+
iterable = Arrays.asList((Object[]) propertyValue);
127+
} else {
128+
throw new RuntimeException("Don't know how to handle " + propertyValue.getClass() + " type of collection");
129+
}
130+
131+
for (Object listValue : iterable) {
132+
133+
if (listValue != null) {
134+
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, listValue);
135+
indexes.addAll(
123136
doResolveIndexesFor(keyspace, currentPath, typeToUse.getActualType(), persistentProperty, listValue));
137+
}
124138
}
125139
}
126140

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.util.Date;
4444
import java.util.HashMap;
4545
import java.util.LinkedHashMap;
46+
import java.util.List;
4647
import java.util.Map;
4748
import java.util.UUID;
4849

@@ -146,7 +147,7 @@ public void writeDoesNotAppendPropertiesWithNullValues() {
146147
* @see DATAREDIS-425
147148
*/
148149
@Test
149-
public void writeDoesNotAppendPropertiesWithEmtpyCollections() {
150+
public void writeDoesNotAppendPropertiesWithEmptyCollections() {
150151

151152
rand.firstname = "rand";
152153

@@ -435,6 +436,27 @@ public void writeAppendsMapWithSimpleKeyCorrectly() {
435436
.containingUtf8String("physicalAttributes.[eye-color]", "grey"));
436437
}
437438

439+
/**
440+
* @see DATAREDIS-492
441+
*/
442+
@Test
443+
public void writeHandlesArraysProperly() {
444+
445+
this.converter = new MappingRedisConverter(null, null, resolverMock);
446+
this.converter
447+
.setCustomConversions(new CustomConversions(Collections.singletonList(new ListToByteConverter())));
448+
this.converter.afterPropertiesSet();
449+
450+
Map<String, Object> innerMap = new LinkedHashMap<String, Object>();
451+
innerMap.put("address", "tyrionl@netflix.com");
452+
innerMap.put("when", new String[]{"pipeline.failed"});
453+
454+
Map<String, Object> map = new LinkedHashMap<String, Object>();
455+
map.put("email", Collections.singletonList(innerMap));
456+
457+
RedisData target = write(map);
458+
}
459+
438460
/**
439461
* @see DATAREDIS-425
440462
*/
@@ -1375,6 +1397,35 @@ public Map<String, byte[]> convert(Species source) {
13751397
}
13761398
}
13771399

1400+
@WritingConverter
1401+
static class ListToByteConverter implements Converter<List, byte[]> {
1402+
1403+
private final ObjectMapper mapper;
1404+
private final Jackson2JsonRedisSerializer<List> serializer;
1405+
1406+
ListToByteConverter() {
1407+
1408+
mapper = new ObjectMapper();
1409+
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
1410+
.withFieldVisibility(Visibility.ANY).withGetterVisibility(Visibility.NONE)
1411+
.withSetterVisibility(Visibility.NONE).withCreatorVisibility(Visibility.NONE));
1412+
1413+
serializer = new Jackson2JsonRedisSerializer<List>(List.class);
1414+
serializer.setObjectMapper(mapper);
1415+
}
1416+
1417+
@Override
1418+
public byte[] convert(List source) {
1419+
1420+
if (source == null || source.isEmpty()) {
1421+
return null;
1422+
}
1423+
1424+
return serializer.serialize(source);
1425+
}
1426+
}
1427+
1428+
13781429
@ReadingConverter
13791430
static class MapToSpeciesConverter implements Converter<Map<String, byte[]>, Species> {
13801431

0 commit comments

Comments
 (0)