DATAREDIS-492 - Handle serializing arrays and collections.
Original Pull Request: #189
This commit is contained in:
committed by
Christoph Strobl
parent
deec98efc6
commit
2492fbe332
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.redis.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -100,6 +101,7 @@ import org.springframework.util.comparator.NullSafeComparator;
|
||||
* </pre>
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Greg Turnquist
|
||||
* @since 1.7
|
||||
*/
|
||||
public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
@@ -355,8 +357,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
sink.setTimeToLive(ttl);
|
||||
}
|
||||
|
||||
for (IndexedData indexeData : indexResolver.resolveIndexesFor(entity.getTypeInformation(), source)) {
|
||||
sink.addIndexedData(indexeData);
|
||||
for (IndexedData indexedData : indexResolver.resolveIndexesFor(entity.getTypeInformation(), source)) {
|
||||
sink.addIndexedData(indexedData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -409,8 +411,22 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
writeMap(keyspace, propertyStringPath, persistentProperty.getMapValueType(),
|
||||
(Map<?, ?>) accessor.getProperty(persistentProperty), sink);
|
||||
} else if (persistentProperty.isCollectionLike()) {
|
||||
writeCollection(keyspace, propertyStringPath, (Collection<?>) accessor.getProperty(persistentProperty),
|
||||
|
||||
final Object property = accessor.getProperty(persistentProperty);
|
||||
|
||||
if (property == null || Iterable.class.isAssignableFrom(property.getClass())) {
|
||||
|
||||
writeCollection(keyspace, propertyStringPath, (Iterable<?>) property,
|
||||
persistentProperty.getTypeInformation().getComponentType(), sink);
|
||||
} else if (property.getClass().isArray()) {
|
||||
|
||||
writeCollection(keyspace, propertyStringPath, Arrays.asList((Object[]) property),
|
||||
persistentProperty.getTypeInformation().getComponentType(), sink);
|
||||
} else {
|
||||
|
||||
throw new RuntimeException("Don't know how to handle " + property.getClass() + " type collection");
|
||||
}
|
||||
|
||||
} else if (persistentProperty.isEntity()) {
|
||||
writeInternal(keyspace, propertyStringPath, accessor.getProperty(persistentProperty),
|
||||
persistentProperty.getTypeInformation().getActualType(), sink);
|
||||
@@ -482,7 +498,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @param typeHint
|
||||
* @param sink
|
||||
*/
|
||||
private void writeCollection(String keyspace, String path, Collection<?> values, TypeInformation<?> typeHint,
|
||||
private void writeCollection(String keyspace, String path, Iterable<?> values, TypeInformation<?> typeHint,
|
||||
RedisData sink) {
|
||||
|
||||
if (values == null) {
|
||||
@@ -492,6 +508,10 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
int i = 0;
|
||||
for (Object value : values) {
|
||||
|
||||
if (value == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
String currentPath = path + ".[" + i + "]";
|
||||
|
||||
if (customConversions.hasCustomWriteTarget(value.getClass())) {
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core.convert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
@@ -43,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* {@link IndexConfiguration}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Greg Turnquist
|
||||
* @since 1.7
|
||||
*/
|
||||
public class PathIndexResolver implements IndexResolver {
|
||||
@@ -116,11 +119,23 @@ public class PathIndexResolver implements IndexResolver {
|
||||
|
||||
} else if (persistentProperty.isCollectionLike()) {
|
||||
|
||||
for (Object listValue : (Iterable<?>) propertyValue) {
|
||||
final Iterable<?> iterable;
|
||||
|
||||
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, listValue);
|
||||
indexes.addAll(
|
||||
if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
|
||||
iterable = (Iterable) propertyValue;
|
||||
} else if (propertyValue.getClass().isArray()) {
|
||||
iterable = Arrays.asList((Object[]) propertyValue);
|
||||
} else {
|
||||
throw new RuntimeException("Don't know how to handle " + propertyValue.getClass() + " type of collection");
|
||||
}
|
||||
|
||||
for (Object listValue : iterable) {
|
||||
|
||||
if (listValue != null) {
|
||||
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, listValue);
|
||||
indexes.addAll(
|
||||
doResolveIndexesFor(keyspace, currentPath, typeToUse.getActualType(), persistentProperty, listValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -75,6 +76,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MappingRedisConverterUnitTests {
|
||||
@@ -146,7 +148,7 @@ public class MappingRedisConverterUnitTests {
|
||||
* @see DATAREDIS-425
|
||||
*/
|
||||
@Test
|
||||
public void writeDoesNotAppendPropertiesWithEmtpyCollections() {
|
||||
public void writeDoesNotAppendPropertiesWithEmptyCollections() {
|
||||
|
||||
rand.firstname = "rand";
|
||||
|
||||
@@ -435,6 +437,27 @@ public class MappingRedisConverterUnitTests {
|
||||
.containingUtf8String("physicalAttributes.[eye-color]", "grey"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-492
|
||||
*/
|
||||
@Test
|
||||
public void writeHandlesArraysProperly() {
|
||||
|
||||
this.converter = new MappingRedisConverter(null, null, resolverMock);
|
||||
this.converter
|
||||
.setCustomConversions(new CustomConversions(Collections.singletonList(new ListToByteConverter())));
|
||||
this.converter.afterPropertiesSet();
|
||||
|
||||
Map<String, Object> innerMap = new LinkedHashMap<String, Object>();
|
||||
innerMap.put("address", "tyrionl@netflix.com");
|
||||
innerMap.put("when", new String[]{"pipeline.failed"});
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
map.put("email", Collections.singletonList(innerMap));
|
||||
|
||||
RedisData target = write(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREDIS-425
|
||||
*/
|
||||
@@ -1375,6 +1398,35 @@ public class MappingRedisConverterUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
static class ListToByteConverter implements Converter<List, byte[]> {
|
||||
|
||||
private final ObjectMapper mapper;
|
||||
private final Jackson2JsonRedisSerializer<List> serializer;
|
||||
|
||||
ListToByteConverter() {
|
||||
|
||||
mapper = new ObjectMapper();
|
||||
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
|
||||
.withFieldVisibility(Visibility.ANY).withGetterVisibility(Visibility.NONE)
|
||||
.withSetterVisibility(Visibility.NONE).withCreatorVisibility(Visibility.NONE));
|
||||
|
||||
serializer = new Jackson2JsonRedisSerializer<List>(List.class);
|
||||
serializer.setObjectMapper(mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convert(List source) {
|
||||
|
||||
if (source == null || source.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return serializer.serialize(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ReadingConverter
|
||||
static class MapToSpeciesConverter implements Converter<Map<String, byte[]>, Species> {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user