Skip to content

Commit 52c2d58

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 0897825 commit 52c2d58

File tree

2 files changed

+87
-5
lines changed

2 files changed

+87
-5
lines changed

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

Lines changed: 61 additions & 5 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;
@@ -153,6 +155,8 @@
153155
*/
154156
public class Jackson2HashMapper implements HashMapper<Object, String, Object>, HashObjectReader<String, Object> {
155157

158+
private static final boolean SOURCE_VERSION_PRESENT = ClassUtils.isPresent("javax.lang.model.SourceVersion", Jackson2HashMapper.class.getClassLoader());
159+
156160
private final HashMapperModule HASH_MAPPER_MODULE = new HashMapperModule();
157161

158162
private final ObjectMapper typingMapper;
@@ -287,8 +291,7 @@ public <R> R fromHash(Class<R> type, Map<String, Object> hash) {
287291

288292
if (flatten) {
289293

290-
return typingMapper.reader().forType(type)
291-
.readValue(untypedMapper.writeValueAsBytes(doUnflatten(hash)));
294+
return typingMapper.reader().forType(type).readValue(untypedMapper.writeValueAsBytes(doUnflatten(hash)));
292295
}
293296

294297
return typingMapper.treeToValue(untypedMapper.valueToTree(hash), type);
@@ -394,10 +397,42 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
394397
if (cur.isArray()) {
395398
this.flattenCollection(propertyPrefix, cur.elements(), resultMap);
396399
} else {
400+
if (nodes.hasNext() && mightBeJavaType(cur)) {
401+
402+
JsonNode next = nodes.next();
403+
404+
if (next.isArray()) {
405+
this.flattenCollection(propertyPrefix, next.elements(), resultMap);
406+
}
407+
408+
if (cur.asText().equals("java.util.Date")) {
409+
resultMap.put(propertyPrefix, next.asText());
410+
break;
411+
}
412+
if (next.isNumber()) {
413+
resultMap.put(propertyPrefix, next.numberValue());
414+
break;
415+
}
416+
if (next.isTextual()) {
417+
418+
resultMap.put(propertyPrefix, next.textValue());
419+
break;
420+
}
421+
if (next.isBoolean()) {
422+
423+
resultMap.put(propertyPrefix, next.booleanValue());
424+
break;
425+
}
426+
if (next.isBinary()) {
427+
428+
try {
429+
resultMap.put(propertyPrefix, next.binaryValue());
430+
} catch (IOException e) {
431+
throw new IllegalStateException(String.format("Cannot read binary value of '%s'", propertyPrefix), e);
432+
}
433+
break;
434+
}
397435

398-
if (cur.asText().equals("java.util.Date")) {
399-
resultMap.put(propertyPrefix, nodes.next().asText());
400-
break;
401436
}
402437
}
403438
}
@@ -409,6 +444,27 @@ private void flattenElement(String propertyPrefix, Object source, Map<String, Ob
409444
}
410445
}
411446

447+
private boolean mightBeJavaType(JsonNode node) {
448+
449+
String textValue = node.asText();
450+
if (!SOURCE_VERSION_PRESENT) {
451+
452+
if (ObjectUtils.nullSafeEquals(textValue, "java.util.Date")) {
453+
return true;
454+
}
455+
if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigInteger")) {
456+
return true;
457+
}
458+
if (ObjectUtils.nullSafeEquals(textValue, "java.math.BigDecimal")) {
459+
return true;
460+
}
461+
462+
return false;
463+
}
464+
return javax.lang.model.SourceVersion.isName(textValue);
465+
466+
}
467+
412468
private void flattenCollection(String propertyPrefix, Iterator<JsonNode> list, Map<String, Object> resultMap) {
413469

414470
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
@@ -19,6 +19,8 @@
1919

2020
import lombok.Data;
2121

22+
import java.math.BigDecimal;
23+
import java.math.BigInteger;
2224
import java.time.LocalDate;
2325
import java.time.LocalDateTime;
2426
import java.util.ArrayList;
@@ -199,6 +201,24 @@ void mapFinalClass() {
199201
assertBackAndForwardMapping(source);
200202
}
201203

204+
@Test // GH-2365
205+
void bigIntegerShouldBeTreatedCorrectly() {
206+
207+
WithBigWhatever source = new WithBigWhatever();
208+
source.bigI = BigInteger.TEN;
209+
210+
assertBackAndForwardMapping(source);
211+
}
212+
213+
@Test // GH-2365
214+
void bigDecimalShouldBeTreatedCorrectly() {
215+
216+
WithBigWhatever source = new WithBigWhatever();
217+
source.bigD = BigDecimal.ONE;
218+
219+
assertBackAndForwardMapping(source);
220+
}
221+
202222
@Data
203223
public static class WithList {
204224
List<String> strings;
@@ -223,6 +243,12 @@ private static class WithDates {
223243
private LocalDateTime localDateTime;
224244
}
225245

246+
@Data
247+
private static class WithBigWhatever {
248+
private BigDecimal bigD;
249+
private BigInteger bigI;
250+
}
251+
226252
@Data
227253
public static final class MeFinal {
228254
private String value;

0 commit comments

Comments
 (0)