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?
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)));
}