From 637964eed84e170fac224924e86fec17c7d35759 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 6 Jun 2023 10:27:02 +0200 Subject: [PATCH] Fix Jackson (hash) mapping for BigDecimal/BigInteger scalar values and Java Time types. Once again, the SD Redis Jackson2HashMapper can now de/serialize Objects with BigDecimal/BigInteger values along with java.time types, such as java.time.LocalDateTime. Additionally, splits the unit tests for flattening and unflattening of the hash mapping into 2 separate test classes to be picked up in the SD Redis test suite. Resolves #2593 --- .../data/redis/hash/Jackson2HashMapper.java | 10 ++++++- ...Jackson2HashMapperFlatteningUnitTests.java | 29 +++++++++++++++++++ ...kson2HashMapperNonFlatteningUnitTests.java | 29 +++++++++++++++++++ .../mapping/Jackson2HashMapperUnitTests.java | 25 +++++----------- 4 files changed, 75 insertions(+), 18 deletions(-) create mode 100644 src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperFlatteningUnitTests.java create mode 100644 src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperNonFlatteningUnitTests.java 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 7d7406e6f..822bbc644 100644 --- a/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java +++ b/src/main/java/org/springframework/data/redis/hash/Jackson2HashMapper.java @@ -54,6 +54,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.SerializationFeature; @@ -183,6 +184,10 @@ public class Jackson2HashMapper implements HashMapper { return false; } + if(flatten && t.isTypeOrSubTypeOf(Number.class)) { + return false; + } + if (EVERYTHING.equals(_appliesFor)) { return !TreeNode.class.isAssignableFrom(t.getRawClass()); } @@ -196,6 +201,9 @@ public class Jackson2HashMapper implements HashMapper { typingMapper.activateDefaultTyping(typingMapper.getPolymorphicTypeValidator(), DefaultTyping.EVERYTHING, As.PROPERTY); typingMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); + if(flatten) { + typingMapper.disable(MapperFeature.REQUIRE_TYPE_ID_FOR_SUBTYPES); + } // Prevent splitting time types into arrays. E typingMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); @@ -240,7 +248,7 @@ public class Jackson2HashMapper implements HashMapper { Map unflattenedHash = doUnflatten(hash); byte[] unflattenedHashedBytes = untypedMapper.writeValueAsBytes(unflattenedHash); Object hashedObject = typingMapper.reader().forType(Object.class) - .readValue(unflattenedHashedBytes);; + .readValue(unflattenedHashedBytes); return hashedObject; } diff --git a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperFlatteningUnitTests.java b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperFlatteningUnitTests.java new file mode 100644 index 000000000..014ed603d --- /dev/null +++ b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperFlatteningUnitTests.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.mapping; + +import org.springframework.data.redis.hash.Jackson2HashMapper; + +/** + * @author Christoph Strobl + * @since 2023/06 + */ +public class Jackson2HashMapperFlatteningUnitTests extends Jackson2HashMapperUnitTests { + + Jackson2HashMapperFlatteningUnitTests() { + super(new Jackson2HashMapper(true)); + } +} diff --git a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperNonFlatteningUnitTests.java b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperNonFlatteningUnitTests.java new file mode 100644 index 000000000..588604ce1 --- /dev/null +++ b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperNonFlatteningUnitTests.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.mapping; + +import org.springframework.data.redis.hash.Jackson2HashMapper; + +/** + * @author Christoph Strobl + * @since 2023/06 + */ +public class Jackson2HashMapperNonFlatteningUnitTests extends Jackson2HashMapperUnitTests { + + Jackson2HashMapperNonFlatteningUnitTests() { + super(new Jackson2HashMapper(false)); + } +} 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 7eb156559..c1d1a01f8 100644 --- a/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java +++ b/src/test/java/org/springframework/data/redis/mapping/Jackson2HashMapperUnitTests.java @@ -15,6 +15,8 @@ */ package org.springframework.data.redis.mapping; +import static org.assertj.core.api.Assertions.*; + import lombok.Data; import java.math.BigDecimal; @@ -28,9 +30,11 @@ import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Stream; +import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.Test; - +import org.junit.jupiter.api.TestFactory; import org.springframework.data.redis.Address; import org.springframework.data.redis.Person; import org.springframework.data.redis.hash.HashMapper; @@ -44,23 +48,10 @@ import org.springframework.data.redis.hash.Jackson2HashMapper; */ public abstract class Jackson2HashMapperUnitTests extends AbstractHashMapperTests { - private final Jackson2HashMapper mapper; + private Jackson2HashMapper mapper; - Jackson2HashMapperUnitTests(Jackson2HashMapper mapper) { - this.mapper = mapper; - } - - static class FlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests { - FlatteningJackson2HashMapperUnitTests() { - super(new Jackson2HashMapper(true)); - } - } - - static class NonFlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests { - - NonFlatteningJackson2HashMapperUnitTests() { - super(new Jackson2HashMapper(false)); - } + public Jackson2HashMapperUnitTests(Jackson2HashMapper param){ + this.mapper = param; } @Override