From abf40297dd91d64196fa6ffd9bc635e67b0f0381 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 14 Jul 2022 16:18:44 +0200 Subject: [PATCH] Fix HashMapper issue flattening java.math types. We now make sure to include types from the java.math namespace. Closes: #2365 --- .../data/redis/hash/Jackson2HashMapper.java | 63 ++++++++++++++++++- .../mapping/Jackson2HashMapperUnitTests.java | 26 ++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java b/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java index 72be86b6c..567c9617e 100644 --- a/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java +++ b/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java @@ -34,7 +34,9 @@ import java.util.Set; import org.springframework.data.mapping.MappingException; import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.NumberUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -150,6 +152,8 @@ import com.fasterxml.jackson.databind.ser.std.DateSerializer; */ public class Jackson2HashMapper implements HashMapper { + private static final boolean SOURCE_VERSION_PRESENT = ClassUtils.isPresent("javax.lang.model.SourceVersion", Jackson2HashMapper.class.getClassLoader()); + private final HashMapperModule HASH_MAPPER_MODULE = new HashMapperModule(); private final ObjectMapper typingMapper; @@ -336,10 +340,42 @@ public class Jackson2HashMapper implements HashMapper { if (cur.isArray()) { this.flattenCollection(propertyPrefix, cur.elements(), resultMap); } else { + if (nodes.hasNext() && mightBeJavaType(cur)) { + + JsonNode next = nodes.next(); + + if (next.isArray()) { + this.flattenCollection(propertyPrefix, next.elements(), resultMap); + } + + if (cur.asText().equals("java.util.Date")) { + resultMap.put(propertyPrefix, next.asText()); + break; + } + if (next.isNumber()) { + resultMap.put(propertyPrefix, next.numberValue()); + break; + } + if (next.isTextual()) { + + resultMap.put(propertyPrefix, next.textValue()); + break; + } + if (next.isBoolean()) { + + resultMap.put(propertyPrefix, next.booleanValue()); + break; + } + if (next.isBinary()) { + + try { + resultMap.put(propertyPrefix, next.binaryValue()); + } catch (IOException e) { + throw new IllegalStateException(String.format("Cannot read binary value of '%s'", propertyPrefix), e); + } + break; + } - if (cur.asText().equals("java.util.Date")) { - resultMap.put(propertyPrefix, nodes.next().asText()); - break; } } } @@ -351,6 +387,27 @@ public class Jackson2HashMapper implements HashMapper { } } + private boolean mightBeJavaType(JsonNode node) { + + String textValue = node.asText(); + if (!SOURCE_VERSION_PRESENT) { + + if (ObjectUtils.nullSafeEquals(textValue, "java.util.Date")) { + return true; + } + if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigInteger")) { + return true; + } + if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigDecimal")) { + return true; + } + + return false; + } + return javax.lang.model.SourceVersion.isName(textValue); + + } + private void flattenCollection(String propertyPrefix, Iterator list, Map resultMap) { int counter = 0; diff --git a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java index 4a1673ae5..c49236921 100644 --- a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java +++ b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java @@ -17,6 +17,8 @@ package org.springframework.data.redis.mapping; import lombok.Data; +import java.math.BigDecimal; +import java.math.BigInteger; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; @@ -192,6 +194,24 @@ public abstract class Jackson2HashMapperUnitTests extends AbstractHashMapperTest assertBackAndForwardMapping(source); } + @Test // GH-2365 + void bigIntegerShouldBeTreatedCorrectly() { + + WithBigWhatever source = new WithBigWhatever(); + source.bigI = BigInteger.TEN; + + assertBackAndForwardMapping(source); + } + + @Test // GH-2365 + void bigDecimalShouldBeTreatedCorrectly() { + + WithBigWhatever source = new WithBigWhatever(); + source.bigD = BigDecimal.ONE; + + assertBackAndForwardMapping(source); + } + @Data public static class WithList { List strings; @@ -216,6 +236,12 @@ public abstract class Jackson2HashMapperUnitTests extends AbstractHashMapperTest private LocalDateTime localDateTime; } + @Data + private static class WithBigWhatever { + private BigDecimal bigD; + private BigInteger bigI; + } + @Data public static final class MeFinal { private String value;