Reputation: 1888
I an using redis cache and faced the problem: map with integer key is serialized as String like this:
"1":"AAAA","2":"BBB","3":"CCC"
This is how my config looks like:
@Bean
public RedisCacheConfiguration myCacheConfiguration()
{
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ZERO)
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new Jackson2JsonRedisSerializer<>(Map.class)));
}
@Bean
public CacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory)
{
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(myCacheConfiguration())
.transactionAware()
.build();
}
I tried to pass GenericJackson2JsonRedisSerializer to serializeValuesWith(), but is doesn't work. Is there any way to serialize\deserialize Integer keys of map as number?
Upvotes: 0
Views: 4014
Reputation: 1888
The issue is easily solved by adding overriding of method JavaType getJavaType(Class clazz) in Jackson2JsonRedisSerializer. Documentation says:
/**
* Returns the Jackson {@link JavaType} for the specific class.
* <p>
* Default implementation returns {@link TypeFactory#constructType(java.lang.reflect.Type)}, but this can be
* overridden in subclasses, to allow for custom generic collection handling. For instance:
*
* <pre class="code">
* protected JavaType getJavaType(Class<?> clazz) {
* if (List.class.isAssignableFrom(clazz)) {
* return TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, MyBean.class);
* } else {
* return super.getJavaType(clazz);
* }
* }
* </pre>
*
* @param clazz the class to return the java type for
* @return the java type
*/
protected JavaType getJavaType(Class<?> clazz) {
return TypeFactory.defaultInstance().constructType(clazz);
}
So, I just overriding this method like this:
public class CustomSerializer extends Jackson2JsonRedisSerializer
{
public JurisdictionsSerializer(Class type)
{
super(type);
}
@Override
protected JavaType getJavaType(Class clazz)
{
return TypeFactory.defaultInstance()
.constructMapType(Map.class, Integer.class, String.class);
}
}
And then add this serializer to redis configuration like this:
@Bean
public RedisCacheConfiguration myCacheConfiguration()
{
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ZERO)
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new CustomSerializer(Map.class)));
}
Upvotes: 0
Reputation: 364
Jackson2JsonRedisSerializer
and GenericJackson2JsonRedisSerializer
both allow to use custom ObjectMapper
.
No familiar with Redis, but seems that's designed way for custom serialization according to the doc:
Setting a custom-configured
ObjectMapper
is one way to take further control of the JSON serialization process. For example, an extendedSerializerFactory
can be configured that provides custom serializers for specific types. The other option for refining the serialization process is to use Jackson's provided annotations on the types to be serialized, in which case a custom-configured ObjectMapper is unnecessary.
Upvotes: 1