Resolve target type of wrapped one in custom StdTypeResolverBuilder.
This commit makes sure to avoid typing of primitive wrapper types wrapped inside what is considered a jackson ReferenceType (such as Optional, AtomicReference,...). Original Pull Request: #2364
This commit is contained in:
@@ -235,21 +235,33 @@ public class GenericJackson2JsonRedisSerializer implements RedisSerializer<Objec
|
||||
return true;
|
||||
}
|
||||
|
||||
while (t.isArrayType()) {
|
||||
t = t.getContentType();
|
||||
}
|
||||
t = resolveArrayOrWrapper(t);
|
||||
|
||||
if (ClassUtils.isPrimitiveOrWrapper(t.getRawClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 19-Apr-2016, tatu: ReferenceType like Optional also requires similar handling:
|
||||
while (t.isReferenceType()) {
|
||||
t = t.getReferencedType();
|
||||
}
|
||||
|
||||
// [databind#88] Should not apply to JSON tree models:
|
||||
return !TreeNode.class.isAssignableFrom(t.getRawClass());
|
||||
}
|
||||
|
||||
private JavaType resolveArrayOrWrapper(JavaType type) {
|
||||
|
||||
while (type.isArrayType()) {
|
||||
type = type.getContentType();
|
||||
if (type.isReferenceType()) {
|
||||
type = resolveArrayOrWrapper(type);
|
||||
}
|
||||
}
|
||||
|
||||
while (type.isReferenceType()) {
|
||||
type = type.getReferencedType();
|
||||
if (type.isArrayType()) {
|
||||
type = resolveArrayOrWrapper(type);
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.springframework.util.ObjectUtils.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -168,7 +169,7 @@ class GenericJackson2JsonRedisSerializerUnitTests {
|
||||
}
|
||||
|
||||
@Test // GH-2361
|
||||
void shouldDeserializeArrayWithoutTypeHint() {
|
||||
void shouldDeserializePrimitiveArrayWithoutTypeHint() {
|
||||
|
||||
GenericJackson2JsonRedisSerializer gs = new GenericJackson2JsonRedisSerializer();
|
||||
CountAndArray result = (CountAndArray) gs.deserialize(
|
||||
@@ -179,6 +180,87 @@ class GenericJackson2JsonRedisSerializerUnitTests {
|
||||
assertThat(result.getAvailable()).containsExactly(0, 1);
|
||||
}
|
||||
|
||||
@Test // GH-2361
|
||||
void shouldDeserializePrimitiveWrapperArrayWithoutTypeHint() {
|
||||
|
||||
GenericJackson2JsonRedisSerializer gs = new GenericJackson2JsonRedisSerializer();
|
||||
CountAndArray result = (CountAndArray) gs.deserialize(
|
||||
("{\"@class\":\"org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializerUnitTests$CountAndArray\", \"count\":1, \"arrayOfPrimitiveWrapper\":[0,1]}")
|
||||
.getBytes());
|
||||
|
||||
assertThat(result.getCount()).isEqualTo(1);
|
||||
assertThat(result.getArrayOfPrimitiveWrapper()).containsExactly(0L, 1L);
|
||||
}
|
||||
|
||||
@Test // GH-2361
|
||||
void doesNotIncludeTypingForPrimitiveArrayWrappers() {
|
||||
|
||||
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
|
||||
|
||||
WithWrapperTypes source = new WithWrapperTypes();
|
||||
source.primitiveWrapper = new AtomicReference<>();
|
||||
source.primitiveArrayWrapper = new AtomicReference<>(new Integer[] { 200, 300 });
|
||||
source.simpleObjectWrapper = new AtomicReference<>();
|
||||
|
||||
byte[] serializedValue = serializer.serialize(source);
|
||||
|
||||
assertThat(new String(serializedValue)) //
|
||||
.contains("\"primitiveArrayWrapper\":[200,300]") //
|
||||
.doesNotContain("\"[Ljava.lang.Integer;\"");
|
||||
|
||||
assertThat(serializer.deserialize(serializedValue)) //
|
||||
.isInstanceOf(WithWrapperTypes.class) //
|
||||
.satisfies(it -> {
|
||||
WithWrapperTypes deserialized = (WithWrapperTypes) it;
|
||||
assertThat(deserialized.primitiveArrayWrapper).hasValue(source.primitiveArrayWrapper.get());
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2361
|
||||
void doesNotIncludeTypingForPrimitiveWrappers() {
|
||||
|
||||
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
|
||||
|
||||
WithWrapperTypes source = new WithWrapperTypes();
|
||||
source.primitiveWrapper = new AtomicReference<>(123L);
|
||||
|
||||
byte[] serializedValue = serializer.serialize(source);
|
||||
|
||||
assertThat(new String(serializedValue)) //
|
||||
.contains("\"primitiveWrapper\":123") //
|
||||
.doesNotContain("\"Ljava.lang.Long;\"");
|
||||
|
||||
assertThat(serializer.deserialize(serializedValue)) //
|
||||
.isInstanceOf(WithWrapperTypes.class) //
|
||||
.satisfies(it -> {
|
||||
WithWrapperTypes deserialized = (WithWrapperTypes) it;
|
||||
assertThat(deserialized.primitiveWrapper).hasValue(source.primitiveWrapper.get());
|
||||
});
|
||||
}
|
||||
|
||||
@Test // GH-2361
|
||||
void includesTypingForWrappedObjectTypes() {
|
||||
|
||||
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
|
||||
|
||||
SimpleObject simpleObject = new SimpleObject(100L);
|
||||
WithWrapperTypes source = new WithWrapperTypes();
|
||||
source.simpleObjectWrapper = new AtomicReference<>(simpleObject);
|
||||
|
||||
byte[] serializedValue = serializer.serialize(source);
|
||||
|
||||
assertThat(new String(serializedValue)) //
|
||||
.contains(
|
||||
"\"simpleObjectWrapper\":{\"@class\":\"org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializerUnitTests$SimpleObject\",\"longValue\":100}");
|
||||
|
||||
assertThat(serializer.deserialize(serializedValue)) //
|
||||
.isInstanceOf(WithWrapperTypes.class) //
|
||||
.satisfies(it -> {
|
||||
WithWrapperTypes deserialized = (WithWrapperTypes) it;
|
||||
assertThat(deserialized.simpleObjectWrapper).hasValue(source.simpleObjectWrapper.get());
|
||||
});
|
||||
}
|
||||
|
||||
private static void serializeAndDeserializeNullValue(GenericJackson2JsonRedisSerializer serializer) {
|
||||
|
||||
NullValue nv = BeanUtils.instantiateClass(NullValue.class);
|
||||
@@ -228,7 +310,6 @@ class GenericJackson2JsonRedisSerializerUnitTests {
|
||||
return nullSafeEquals(this.stringValue, other.stringValue)
|
||||
&& nullSafeEquals(this.simpleObject, other.simpleObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -275,6 +356,14 @@ class GenericJackson2JsonRedisSerializerUnitTests {
|
||||
|
||||
private int count;
|
||||
private int[] available;
|
||||
private Long[] arrayOfPrimitiveWrapper;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class WithWrapperTypes {
|
||||
|
||||
AtomicReference<Long> primitiveWrapper;
|
||||
AtomicReference<Integer[]> primitiveArrayWrapper;
|
||||
AtomicReference<SimpleObject> simpleObjectWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user