Невозможно десериализировать значение Redis в java pojo - PullRequest
1 голос
/ 22 апреля 2020

Это моя конфигурация redis

@Configuration
public class RedisConfig {

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379);
//        redisStandaloneConfiguration.setPassword(RedisPassword.of("password"));
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        /**
         * Configure your redisTemplate
         * StringRedisTemplate Use String RedisSerializer to serialize by default
         * RedisTemplate By default, use JdkSerialization RedisSerializer to serialize
         */
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //Turn on the default type
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //Set date format
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

Это мои модели

@Data
@AllArgsConstructor
public class User{

   private String id;
   private String name;
   private List<Hobby> hobbies;

   public User() {};
}

@Data
@AllArgsConstructor
public class Hobby {

    private String name;

    public Hobby() {};
}

Это мой репозиторий redis

@Repository
public class RedisUserRepository {

    private HashOperations hashOperations;

    private RedisTemplate redisTemplate;

    public RedisUserRepository(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.hashOperations = this.redisTemplate.opsForHash();
    }

    public void save(String hash, User user) {
        hashOperations.put(hash, user.getId(), user);
    }

    public User findById(String hash, String id) {
        User o = (User) hashOperations.get(hash, id);
        return o;
    }
}

Когда я запускаю это, я Я могу сохранить пользователя 1..

@Override
    public void run(String... args) throws Exception {
        List<Hobby> hobbies = new ArrayList<Hobby>() {{
          add(new Hobby("cricket"));
          add(new Hobby("dancing"));
        }};

        User user1 = new User("2def", "Bob", hobbies);
        this.redisUserRepository.save("USER", user1);

        # ERROR HERE RETRIEVING!
        User retrieved = this.redisUserRepository.findById("USER", "2def");
}

Однако, когда я получаю объект из Redis, он выдает

    Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.testproject.InMemory.InMemoryApplication$1` (no Creators, like default construct, exist): no default no-arguments constructor found
 at [Source: (byte[])"["com.testproject.InMemory.model.User",{"id":"2def","name":"Bob","hobbies":["com.testproject.InMemory.InMemoryApplication$1",[["com.testproject.InMemory.model.Hobby",{"name":"cricket"}],["com.testproject.InMemory.model.Hobby",{"name":"dancing"}]]]}]"; line: 1, column: 126] (through reference chain: com.testproject.InMemory.model.User["hobbies"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1055) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.ValueInstantiator.createUsingDefault(ValueInstantiator.java:189) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createUsingDefault(StdValueInstantiator.java:267) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createDefaultInstance(CollectionDeserializer.java:255) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:120) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserializeWithType(CollectionDeserializer.java:314) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:138) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:120) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromAny(AsArrayTypeDeserializer.java:71) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202) ~[jackson-databind-2.10.2.jar:2.10.2]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3309) ~[jackson-databind-2.10.2.jar:2.10.2]
    at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:73) ~[spring-data-redis-2.2.6.RELEASE.jar:2.2.6.RELEASE]
    ... 25 common frames omitted

Я не могу десериализовать список хобби. Как я могу это исправить? Если у меня нет увлечений List в моем пользовательском классе, код может нормально работать.

- EDIT - мой pom. xml выглядит следующим образом. Я использую Spring boot 2.2.6-RELEASE.

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

1 Ответ

1 голос
/ 22 апреля 2020

Аноним ArrayList может быть вашей проблемой. Вместо:

List<Hobby> hobbies = new ArrayList<Hobby>() {{
  add(new Hobby("cricket"));
  add(new Hobby("dancing"));
}};

Попробуйте:

List<Hobby> hobbies = new ArrayList<Hobby>();
hobbies.add(new Hobby("cricket"));
hobbies.add(new Hobby("dancing"));
...