1
resposta

Erro Deserialize `java.time.LocalTime`

Mensagem de erro: Cannot deserialize value of type java.time.LocalTime from Object value (token JsonToken.START_OBJECT);

Entidade JobForm:

public class JobForm {

    @NotNull
    private String name;
    @NotNull
    private BigDecimal valueOfService;
    @NotNull
    private LocalTime durationTime;

    public String getName() {
        return name;
    }

    public BigDecimal getValueOfService() {
        return valueOfService;
    }

    public LocalTime getDurationTime() {
        return durationTime;
    }

    public Job convert(){
        Job job = new Job();
        job.setName(this.name);
        job.setTimeOfDuration(this.durationTime);
        job.setValueOfService(this.valueOfService);
        return job;
    }

}

Metodo Post do controller:

    @PostMapping
    @Transactional
    @CacheEvict(value = "serviceList", allEntries = true)
    public ResponseEntity<Job> insert(@RequestBody @Valid JobForm jobForm, UriComponentsBuilder uriBuilder) {
        Job savedJob = serviceRepository.save(jobForm.convert());
        URI uri = uriBuilder.path("/service/{id}")
                .buildAndExpand(savedJob.getServiceId())
                .toUri();
        return ResponseEntity.created(uri).body(savedJob);
    }

Já tentei diversas anotações @JsonFormt, @JsonSerialize e JsonDeserialize com jackson e algumas outras e não obtive sucesso, fiz varias pesquisas e também não obtive sucesso. No curso "Como construir uma api rest" não ensina a serializar, pensei até que era feito automaticamente.

1 resposta

Olá Rafael, tudo bem?

O problema que você está enfrentando ocorre porque o Jackson, por padrão, não sabe como serializar e desserializar objetos LocalTime. Você precisa configurar manualmente o Jackson para lidar com o tipo LocalTime.

Uma maneira de fazer isso é criar uma classe personalizada que implemente JsonDeserializer e JsonSerializer para o tipo LocalTime. Aqui está um exemplo de como você pode fazer isso:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.io.IOException;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class LocalTimeJsonSerializer extends JsonSerializer<LocalTime> {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

    @Override
    public void serialize(LocalTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(FORMATTER.format(value));
    }
}

public class LocalTimeJsonDeserializer extends JsonDeserializer<LocalTime> {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

    @Override
    public LocalTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String value = p.getValueAsString();
        return LocalTime.parse(value, FORMATTER);
    }
}

Em seguida, você precisa registrar esses serializadores/desserializadores personalizados no mapeador Jackson que você está usando. No caso do Spring Boot, você pode fazer isso criando uma classe de configuração para o mapeador Jackson:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(LocalTime.class, new LocalTimeJsonSerializer());
        module.addDeserializer(LocalTime.class, new LocalTimeJsonDeserializer());
        objectMapper.registerModule(module);
        return objectMapper;
    }

}

Agora, o Jackson será capaz de serializar e desserializar corretamente objetos LocalTime usando o formato "HH:mm:ss".

Certifique-se de importar as classes necessárias para os serializadores/desserializadores, como JsonSerializer, JsonDeserializer, JsonGenerator, JsonParser e DateTimeFormatter.

Com essa configuração, o Jackson conseguirá serializar e desserializar objetos LocalTime corretamente no seu endpoint POST.

Espero que isso resolva o problema! Se você tiver mais dúvidas, fique à vontade para perguntar.

Espero que isso resolva o seu problema! Se tiver mais alguma dúvida, é só perguntar. Bons estudos!