diff --git a/src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java b/src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java index 9f474f14a..1d62368ba 100644 --- a/src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java +++ b/src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java @@ -15,10 +15,10 @@ */ package org.springframework.data.redis.core.convert; -import lombok.RequiredArgsConstructor; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; import java.lang.reflect.Array; import java.util.*; @@ -844,9 +844,14 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean { throw new IllegalArgumentException( String.format("Cannot extract map value for key '%s' in path '%s'.", entry.getKey(), path)); } - String key = matcher.group(2); + Object key = matcher.group(2); Class typeToUse = getTypeHint(path + ".[" + key + "]", source.getBucket(), valueType); + + if (!keyType.isAssignableFrom(key.getClass())) { + key = conversionService.convert(key, keyType); + } + target.put(key, fromBytes(entry.getValue(), typeToUse)); } @@ -879,7 +884,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean { throw new IllegalArgumentException( String.format("Cannot extract map value for key '%s' in path '%s'.", key, path)); } - String mapKey = matcher.group(2); + Object mapKey = matcher.group(2); Bucket partial = source.getBucket().extract(key); @@ -888,8 +893,13 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean { partial.put(TYPE_HINT_ALIAS, typeInfo); } - Object o = readInternal(key, valueType, new RedisData(partial)); - target.put(mapKey, o); + if (!keyType.isAssignableFrom(mapKey.getClass())) { + mapKey = conversionService.convert(mapKey, keyType); + } + + Object value = readInternal(key, valueType, new RedisData(partial)); + + target.put(mapKey, value); } return target.isEmpty() ? null : target; diff --git a/src/test/java/org/springframework/data/redis/core/convert/ConversionTestEntities.java b/src/test/java/org/springframework/data/redis/core/convert/ConversionTestEntities.java index d521394e8..f49538ef9 100644 --- a/src/test/java/org/springframework/data/redis/core/convert/ConversionTestEntities.java +++ b/src/test/java/org/springframework/data/redis/core/convert/ConversionTestEntities.java @@ -57,6 +57,7 @@ public class ConversionTestEntities { List nicknames; List coworkers; + List positions; Integer age; Boolean alive; Date birthdate; @@ -73,7 +74,9 @@ public class ConversionTestEntities { Address address; Map physicalAttributes; + Map numberMapping; Map relatives; + Map favoredRelatives; @Reference Location location; @Reference List visited; diff --git a/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java b/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java index fa543f563..0d70ebf38 100644 --- a/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java +++ b/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java @@ -275,6 +275,18 @@ public class MappingRedisConverterUnitTests { assertThat(converter.read(Person.class, rdo).nicknames, contains("dragon reborn", "car'a'carn", "lews therin")); } + @Test // DATAREDIS-768 + public void readConvertsUnorderedListOfSimpleIntegerPropertiesCorrectly() { + + Map map = new LinkedHashMap<>(); + map.put("positions.[9]", "0"); + map.put("positions.[10]", "1"); + map.put("positions.[1]", "2"); + RedisData rdo = new RedisData(Bucket.newBucketFromStringMap(map)); + + assertThat(converter.read(Person.class, rdo).positions, contains(2, 0, 1)); + } + @Test // DATAREDIS-425 public void readComplexPropertyCorrectly() { @@ -402,6 +414,22 @@ public class MappingRedisConverterUnitTests { assertThat(target.physicalAttributes.get("eye-color"), is("grey")); } + @Test // DATAREDIS-768 + public void readSimpleIntegerMapValuesCorrectly() { + + Map map = new LinkedHashMap<>(); + map.put("numberMapping.[1]", "2"); + map.put("numberMapping.[3]", "4"); + + RedisData rdo = new RedisData(Bucket.newBucketFromStringMap(map)); + + Person target = converter.read(Person.class, rdo); + + assertThat(target.numberMapping, notNullValue()); + assertThat(target.numberMapping.get(1), is(2)); + assertThat(target.numberMapping.get(3), is(4)); + } + @Test // DATAREDIS-425 public void writeAppendsMapWithComplexObjectsCorrectly() { @@ -437,6 +465,22 @@ public class MappingRedisConverterUnitTests { assertThat(target.relatives.get("step-father").firstname, is("tam")); } + @Test // DATAREDIS-768 + public void readMapWithIntegerKeysAndComplexObjectsCorrectly() { + + Map map = new LinkedHashMap<>(); + map.put("favoredRelatives.[1].firstname", "janduin"); + map.put("favoredRelatives.[2].firstname", "tam"); + + Person target = converter.read(Person.class, new RedisData(Bucket.newBucketFromStringMap(map))); + + assertThat(target.favoredRelatives, notNullValue()); + assertThat(target.favoredRelatives.get(1), notNullValue()); + assertThat(target.favoredRelatives.get(1).firstname, is("janduin")); + assertThat(target.favoredRelatives.get(2), notNullValue()); + assertThat(target.favoredRelatives.get(2).firstname, is("tam")); + } + @Test // DATAREDIS-425 public void writeAppendsClassTypeInformationCorrectlyForMapWithComplexObjects() {