Java 使用class.cast转换从Redis接收的对象失败,使用ObjectMapper.convertValue工作
使用Java 使用class.cast转换从Redis接收的对象失败,使用ObjectMapper.convertValue工作,java,json,spring-boot,jackson,Java,Json,Spring Boot,Jackson,使用Class.cast将对象转换为特定类型与使用ObjectMapper.convertValue执行相同操作有什么区别。 我假设cast内部也使用了jackson,但我认为这里的情况并非如此 我的RedisTemplateConfig: @Bean public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate( ReactiveRedisConnectionFactory factory) {
Class.cast
将对象转换为特定类型与使用ObjectMapper.convertValue
执行相同操作有什么区别。
我假设cast内部也使用了jackson
,但我认为这里的情况并非如此
我的RedisTemplateConfig:
@Bean
public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> valueSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Object> builder =
RedisSerializationContext.newSerializationContext(keySerializer);
RedisSerializationContext<String, Object> context =
builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
@Bean
公共反应器模板反应器模板(
反应器(连接工厂){
StringRedisSerializer keySerializer=新的StringRedisSerializer();
Jackson2JsonRedisSerializer valueSerializer=
新的jackson2json重新序列化程序(Object.class);
RedisSerializationContext.RedisSerializationContextBuilder生成器=
newSerializationContext(keySerializer);
重新序列化上下文=
value(valueSerializer.build();
返回新的ReactiveRedisTemplate(工厂、上下文);
}
SetValueInRedis:
@Override
public <T> Mono<T> setValue(String key, Object value, Class<T> clazz) {
return reactiveValueOps.set(key, value,
Duration.ofDays(SESSION_PERSISTENCE_DURATION))
.map(o -> clazz.cast(value));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(val -> Mono.justOrEmpty(objectMapper.convertValue(val, clazz)));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(o -> Mono.justOrEmpty(clazz.cast(o)));
}
@覆盖
公共Mono setValue(字符串键、对象值、类clazz){
返回reactiveValueOps.set(键、值、,
持续时间天数(会话\持续时间\持续时间))
.map(o->clazz.cast(value));
}
工作GetValueInRedis:
@Override
public <T> Mono<T> setValue(String key, Object value, Class<T> clazz) {
return reactiveValueOps.set(key, value,
Duration.ofDays(SESSION_PERSISTENCE_DURATION))
.map(o -> clazz.cast(value));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(val -> Mono.justOrEmpty(objectMapper.convertValue(val, clazz)));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(o -> Mono.justOrEmpty(clazz.cast(o)));
}
@覆盖
公共值(字符串键,类clazz){
返回reactiveValueOps.get(键)
.flatMap(val->Mono.justOrEmpty(objectMapper.convertValue(val,clazz));
}
获取值的错误版本:
@Override
public <T> Mono<T> setValue(String key, Object value, Class<T> clazz) {
return reactiveValueOps.set(key, value,
Duration.ofDays(SESSION_PERSISTENCE_DURATION))
.map(o -> clazz.cast(value));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(val -> Mono.justOrEmpty(objectMapper.convertValue(val, clazz)));
}
@Override
public <T> Mono<T> getValue(String key, Class<T> clazz) {
return reactiveValueOps.get(key)
.flatMap(o -> Mono.justOrEmpty(clazz.cast(o)));
}
@覆盖
公共值(字符串键,类clazz){
返回reactiveValueOps.get(键)
.flatMap(o->Mono.justOrEmpty(clazz.cast(o));
}
----编辑---
如果我们注意到用于Redis的序列化程序(
Jackson2JsonRedisSerializer
):将对象保存到Redis时,它工作正常。但是,在读取(get)cast
时失败,objectmapper
工作。当我使用Jackson2JsonRedis
序列化程序时,get
命令不应该返回一个应该可以使用Class.cast命令本身强制转换的对象吗?Class.cast
和ObjectMapper.convertValue
是两种完全不同的机制Class.cast
不创建新对象,只返回新类型的旧引用。下面您可以看到如何实现Class.cast
:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
Jackson
从另一端创建来自不同层次结构的新对象并复制内部结构。例如,可以使用反射将Map
转换为POJO
并将POJO
转换为Map
。但是,您不能将对Map
的引用转换为对POJO
的引用
总结:只有这两个方法中的convertValue
方法才能真正实现从一个实例到新实例以及从一种类型到新类型的转换<代码>强制转换仅尝试将引用类型更改为同一对象
另见:
get
命令不应该返回一个应该可以使用Class.cast命令强制转换的对象吗?谢谢。我理解ObjectMapper convertValue工作的原因,因为它试图从传递的对象创建一个新对象。但Redis序列化程序是否应该这样做,从而使我的对象可转换?还是我遗漏了什么?@Karshit,什么reactiveValueOps.get(key)
方法返回?为什么我们需要flatMap
。我从未使用过Redis
,只是想解释Class.cast
和ObjectMapper.convertValue
之间的区别。如果您认为不应该转换任何内容,请使用redis
标记创建新问题,并询问您为什么需要这样做。现在我没有太多关于您的项目的信息和关于Redis
的知识来给您提供好的答案。