Allow users to customize the internal ObjectMapper created by GenericJackson2JsonRedisSerializer.
We now allow the internally created Jackson ObjectMapper to be customized and further configured after construction of the GenericJackson2JsonRedisSerializer when a user does not explicitly provide a custom ObjectMapper during construction. Even when providing a custom ObjectMapper, not all configuration applied by the GenericJackson2JsonRedisSerialzier (such as (standard) type resolution) to the internal ObjectMapper would get applied to the user-provided ObjectMapper as well. Closes #2601
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.data.redis.serializer;
|
||||
import java.io.IOException;
|
||||
import java.io.Serial;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.cache.support.NullValue;
|
||||
@@ -196,12 +197,22 @@ public class GenericJackson2JsonRedisSerializer implements RedisSerializer<Objec
|
||||
return typeHintPropertyName != null ? () -> typeHintPropertyName
|
||||
: Lazy.of(() -> defaultTypingEnabled.get() ? null
|
||||
: mapper.getDeserializationConfig().getDefaultTyper(null)
|
||||
.buildTypeDeserializer(mapper.getDeserializationConfig(),
|
||||
mapper.getTypeFactory().constructType(Object.class), Collections.emptyList())
|
||||
.buildTypeDeserializer(mapper.getDeserializationConfig(),
|
||||
mapper.getTypeFactory().constructType(Object.class), Collections.emptyList())
|
||||
.getPropertyName())
|
||||
.or("@class");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured {@link ObjectMapper} used internally by this {@link GenericJackson2JsonRedisSerializer}
|
||||
* to de/serialize {@link Object objects} as {@literal JSON}.
|
||||
*
|
||||
* @return the configured {@link ObjectMapper}.
|
||||
*/
|
||||
protected ObjectMapper getObjectMapper() {
|
||||
return this.mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(@Nullable Object source) throws SerializationException {
|
||||
|
||||
@@ -248,11 +259,33 @@ public class GenericJackson2JsonRedisSerializer implements RedisSerializer<Objec
|
||||
|
||||
try {
|
||||
return (T) reader.read(mapper, source, resolveType(source, type));
|
||||
} catch (Exception ex) {
|
||||
throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
|
||||
} catch (Exception cause) {
|
||||
String message = String.format("Could not read JSON:%s ", cause.getMessage());
|
||||
throw new SerializationException(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder method used to configure and customize the internal Jackson {@link ObjectMapper} created by
|
||||
* this {@link GenericJackson2JsonRedisSerializer} and used to de/serialize {@link Object objects}
|
||||
* as {@literal JSON}.
|
||||
*
|
||||
* @param objectMapperConfigurer {@link Consumer} used to configure and customize the internal {@link ObjectMapper};
|
||||
* must not be {@literal null}.
|
||||
* @return this {@link GenericJackson2JsonRedisSerializer}.
|
||||
* @throws IllegalArgumentException if the {@link Consumer} used to configure and customize
|
||||
* the internal {@link ObjectMapper} is {@literal null}.
|
||||
*/
|
||||
public GenericJackson2JsonRedisSerializer configure(Consumer<ObjectMapper> objectMapperConfigurer) {
|
||||
|
||||
Assert.notNull(objectMapperConfigurer,
|
||||
"Consumer used to configure and customize ObjectMapper must not be null");
|
||||
|
||||
objectMapperConfigurer.accept(getObjectMapper());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected JavaType resolveType(byte[] source, Class<?> type) throws IOException {
|
||||
|
||||
if (!type.equals(Object.class) || !defaultTypingEnabled.get()) {
|
||||
|
||||
Reference in New Issue
Block a user