Skip to content

Commit abf4029

Browse files
Fix HashMapper issue flattening java.math types.
We now make sure to include types from the java.math namespace. Closes: #2365
1 parent 7f368c4 commit abf4029

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
import org.springframework.data.mapping.MappingException;
3535
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
3636
import org.springframework.util.Assert;
37+
import org.springframework.util.ClassUtils;
3738
import org.springframework.util.NumberUtils;
39+
import org.springframework.util.ObjectUtils;
3840
import org.springframework.util.StringUtils;
3941

4042
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@@ -150,6 +152,8 @@
150152
*/
151153
public class Jackson2HashMapper implements HashMapper<Object, String, Object> {
152154

155+
private static final boolean SOURCE_VERSION_PRESENT = ClassUtils.isPresent("javax.lang.model.SourceVersion", Jackson2HashMapper.class.getClassLoader());
156+
153157
private final HashMapperModule HASH_MAPPER_MODULE = new HashMapperModule();
154158

155159
private final ObjectMapper typingMapper;
@@ -336,10 +340,42 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
336340
if (cur.isArray()) {
337341
this.flattenCollection(propertyPrefix, cur.elements(), resultMap);
338342
} else {
343+
if (nodes.hasNext() && mightBeJavaType(cur)) {
344+
345+
JsonNode next = nodes.next();
346+
347+
if (next.isArray()) {
348+
this.flattenCollection(propertyPrefix, next.elements(), resultMap);
349+
}
350+
351+
if (cur.asText().equals("java.util.Date")) {
352+
resultMap.put(propertyPrefix, next.asText());
353+
break;
354+
}
355+
if (next.isNumber()) {
356+
resultMap.put(propertyPrefix, next.numberValue());
357+
break;
358+
}
359+
if (next.isTextual()) {
360+
361+
resultMap.put(propertyPrefix, next.textValue());
362+
break;
363+
}
364+
if (next.isBoolean()) {
365+
366+
resultMap.put(propertyPrefix, next.booleanValue());
367+
break;
368+
}
369+
if (next.isBinary()) {
370+
371+
try {
372+
resultMap.put(propertyPrefix, next.binaryValue());
373+
} catch (IOException e) {
374+
throw new IllegalStateException(String.format("Cannot read binary value of '%s'", propertyPrefix), e);
375+
}
376+
break;
377+
}
339378

340-
if (cur.asText().equals("java.util.Date")) {
341-
resultMap.put(propertyPrefix, nodes.next().asText());
342-
break;
343379
}
344380
}
345381
}
@@ -351,6 +387,27 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
351387
}
352388
}
353389

390+
private boolean mightBeJavaType(JsonNode node) {
391+
392+
String textValue = node.asText();
393+
if (!SOURCE_VERSION_PRESENT) {
394+
395+
if (ObjectUtils.nullSafeEquals(textValue, "java.util.Date")) {
396+
return true;
397+
}
398+
if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigInteger")) {
399+
return true;
400+
}
401+
if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigDecimal")) {
402+
return true;
403+
}
404+
405+
return false;
406+
}
407+
return javax.lang.model.SourceVersion.isName(textValue);
408+
409+
}
410+
354411
private void flattenCollection(String propertyPrefix, Iterator<JsonNode> list, Map<String, Object> resultMap) {
355412

356413
int counter = 0;

src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import lombok.Data;
1919

20+
import java.math.BigDecimal;
21+
import java.math.BigInteger;
2022
import java.time.LocalDate;
2123
import java.time.LocalDateTime;
2224
import java.util.ArrayList;
@@ -192,6 +194,24 @@ void mapFinalClass() {
192194
assertBackAndForwardMapping(source);
193195
}
194196

197+
@Test // GH-2365
198+
void bigIntegerShouldBeTreatedCorrectly() {
199+
200+
WithBigWhatever source = new WithBigWhatever();
201+
source.bigI = BigInteger.TEN;
202+
203+
assertBackAndForwardMapping(source);
204+
}
205+
206+
@Test // GH-2365
207+
void bigDecimalShouldBeTreatedCorrectly() {
208+
209+
WithBigWhatever source = new WithBigWhatever();
210+
source.bigD = BigDecimal.ONE;
211+
212+
assertBackAndForwardMapping(source);
213+
}
214+
195215
@Data
196216
public static class WithList {
197217
List<String> strings;
@@ -216,6 +236,12 @@ private static class WithDates {
216236
private LocalDateTime localDateTime;
217237
}
218238

239+
@Data
240+
private static class WithBigWhatever {
241+
private BigDecimal bigD;
242+
private BigInteger bigI;
243+
}
244+
219245
@Data
220246
public static final class MeFinal {
221247
private String value;

0 commit comments

Comments
 (0)