com.fasterxml.jackson.databind.exc.InvalidTypeIdException:从redis缓存获取数据时缺少类型id

问题描述 投票:0回答:1

我在spring boot项目中实现了redis缓存。 下面是用于缓存该方法返回的数据的代码。第一次执行时,成功将数据存入缓存。

@Cacheable(value = "ProgramCache", key="#programId")
public String findProgramFromGoogle2(String programId) {
    logger.info("method  executed");
    return "abcd";
}

但是当我第二次执行时,它尝试从缓存中获取数据并抛出异常

在做了一些研究之后,我发现在某个地方我需要创建对象映射器的 bean,我这样做了,但仍然遇到相同的错误。

 2024-07-05 15:35:06.494 ERROR 23172 --- [nio-8652-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/googlewallet] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
at [Source: (byte[])"{}"; line: 1, column: 2]; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
 at [Source: (byte[])"{}"; line: 1, column: 2]] with root cause

    com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
at [Source: (byte[])"{}"; line: 1, column: 2]
at 
com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1794) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1323) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:302) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:166) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:107) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:195) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:710) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526) ~[jackson-databind-2.11.4.jar:2.11.4]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3529) ~[jackson-databind-2.11.4.jar:2.11.4]
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:150) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:130) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:49) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.read(RedisSerializationContext.java:272) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.data.redis.cache.RedisCache.deserializeCacheValue(RedisCache.java:280) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:94) ~[spring-data-redis-2.4.5.jar:2.4.5]
at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.AbstractCacheInvoker.doGet(AbstractCacheInvoker.java:73) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.CacheAspectSupport.findInCaches(CacheAspectSupport.java:571) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:536) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:402) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64) ~[spring-context-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.4.jar:5.3.4]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.4.jar:5.3.4]

RedisConfig.java

@Configuration
public class RedisConfig {

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer<Object> serializer = new GenericJackson2JsonRedisSerializer(objectMapper());
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
        return RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(config)
                .build();
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.activateDefaultTyping(
                BasicPolymorphicTypeValidator.builder()
                        .allowIfBaseType(Object.class)
                        .build(),
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );
        return objectMapper;
    }

}
java spring-boot serialization jackson spring-data-redis
1个回答
0
投票

我们先来分析一下错误日志。

Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property @class

此日志表明,反序列化 JSON 时,Jackson 库未能找到

必要的 
@Class type ID 属性。

回到问题,我们在保存数据时成功持久化了数据,但是从缓存中检索数据时出现了异常。 这表明 Jackson 库反序列化 JSON 时存在问题。


在您的情况下,使用 @JsonTypeInfo 注释可能是一个解决方案。

@JsonTypeInfo(
    use = JsonTypeInfo.Id.CLASS,
    include = JsonTypeInfo.As.PROPERTY,
    property = "@class",
    defaultImpl = YourCachedObject.class
)
public class YourCachedObject {
    // methods
}

您可以使用 defaultImpl 选项指定当在 JSON 中找不到类型信息时要使用的

默认实现类

如果此方法不能解决问题,请向我显示附加代码,以便我可以提供更准确的响应

相关文件

© www.soinside.com 2019 - 2024. All rights reserved.