Retain target type hint when deserializing Stream records.

We now retain the target type when obtaining a HashMapper through StreamObjectMapper. To achieve this, we introduced the HashObjectReader interface accepting a target type.

Resolves: #2198
Related: #1566
Original Pull Request: #2253
This commit is contained in:
Mark Paluch
2022-02-02 15:38:37 +01:00
committed by Christoph Strobl
parent 1932a4ca27
commit 73b49862df
9 changed files with 254 additions and 37 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2022 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.core;
import static org.assertj.core.api.Assertions.*;
import lombok.Data;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.springframework.data.redis.hash.Jackson2HashMapper;
import org.springframework.data.redis.hash.ObjectHashMapper;
/**
* Unit tests for {@link StreamObjectMapper}.
*
* @author Mark Paluch
*/
class StreamObjectMapperUnitTests {
@Test // GH-2198
void shouldRetainTypeHintUsingObjectHashMapper() {
StreamObjectMapper mapper = new StreamObjectMapper(ObjectHashMapper.getSharedInstance());
MyType result = mapper.getHashMapper(MyType.class)
.fromHash(Collections.singletonMap("value".getBytes(), "hello".getBytes()));
assertThat(result.value).isEqualTo("hello");
}
@Test // GH-2198
void shouldRetainTypeHintUsingJackson() {
StreamObjectMapper mapper = new StreamObjectMapper(new Jackson2HashMapper(true));
MyType result = mapper.getHashMapper(MyType.class).fromHash(Collections.singletonMap("value", "hello"));
assertThat(result.value).isEqualTo("hello");
}
@Data
static class MyType {
String value;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2021 the original author or authors.
* Copyright 2016-2022 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.
@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.mapping;
import static org.assertj.core.api.Assertions.*;
import lombok.Data;
import java.time.LocalDate;
@@ -48,13 +50,13 @@ public abstract class Jackson2HashMapperUnitTests extends AbstractHashMapperTest
this.mapper = mapper;
}
static class FlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests {
public static class FlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests {
FlatteningJackson2HashMapperUnitTests() {
super(new Jackson2HashMapper(true));
}
}
static class NonFlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests {
public static class NonFlatteningJackson2HashMapperUnitTests extends Jackson2HashMapperUnitTests {
NonFlatteningJackson2HashMapperUnitTests() {
super(new Jackson2HashMapper(false));
@@ -183,6 +185,24 @@ public abstract class Jackson2HashMapperUnitTests extends AbstractHashMapperTest
assertBackAndForwardMapping(source);
}
@Test // GH-2198
void shouldDeserializeObjectWithoutClassHint() {
WithDates source = new WithDates();
source.string = "id-1";
source.date = new Date(1561543964015L);
source.calendar = Calendar.getInstance();
source.localDate = LocalDate.parse("2018-01-02");
source.localDateTime = LocalDateTime.parse("2018-01-02T12:13:14");
Map<String, Object> map = mapper.toHash(source);
// ensure that we remove the correct type hint
assertThat(map.remove("@class")).isNotNull();
assertThat(mapper.fromHash(WithDates.class, map)).isEqualTo(source);
}
@Test // GH-1566
void mapFinalClass() {

View File

@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.*;
import lombok.Data;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
@@ -83,6 +84,18 @@ class ObjectHashMapperTests extends AbstractHashMapperTests {
assertThat(objectHashMapper.fromHash(hash)).isEqualTo(source);
}
@Test // GH-2198
void readHashConsidersTypeHint() {
Map<byte[], byte[]> hash = new LinkedHashMap<>();
hash.put("value".getBytes(), "hello".getBytes());
ObjectHashMapper objectHashMapper = ObjectHashMapper.getSharedInstance();
WithTypeAlias withTypeAlias = objectHashMapper.fromHash(WithTypeAlias.class, hash);
assertThat(withTypeAlias.value).isEqualTo("hello");
}
@TypeAlias("_42_")
@Data
static class WithTypeAlias {