Serialização LocalDateTime[RESOLVIDO]

Olá a todos,

Estou tentando serializar um objeto que possui uma data com a classe LocalDateTime utilizando o Spring Boot, mas o seguinte erro:

2016-10-09 18:28:26.218 WARN 17395 — [ XNIO-2 task-2] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Text ‘2016-10-09T13:00:00.000Z’ could not be parsed at index 2 (through reference chain: br.com.wt.agendadoador.modelo.Agenda[“date”]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Text ‘2016-10-09T13:00:00.000Z’ could not be parsed at index 2 (through reference chain: br.com.wt.agendadoador.modelo.Agenda[“date”])

Fiz algumas pesquisas mas não consegui encontrar o motivo…

Trecho da classe:

@Entity
public class Agenda {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="doador_id")
	@JsonProperty
	private Doador doador;
	@Enumerated(EnumType.STRING)
	private StatusAgenda statusAgenda;
	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="laboratorio_id")
	@JsonProperty
	private Laboratorio laboratorio;
	@JsonFormat(pattern = "dd-MM-yyyy HH:mm:ss")
	@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
	private LocalDateTime date;

Minha configuração no application.properties e Jackson-datetype-jrs310:

spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS =false
 <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>`

Por fim o Controller

@RestController
@RequestMapping(value = "agenda")
public class AgendaController {
	
	@Autowired
	private AgendaRepository agendaRepository;

	@RequestMapping(value = "/", method = RequestMethod.POST,headers="Accept=application/json", produces = "application/json")
	@JsonDeserialize(using = LocalDateTimeDeserializer.class)
	public ResponseEntity<Void> add(@Valid @RequestBody Agenda agenda) {
		HttpHeaders headers = new HttpHeaders();
		try {
			agenda.setStatusAgenda(StatusAgenda.EMABERTO);
			agendaRepository.save(agenda);
			return new ResponseEntity<Void>(headers, HttpStatus.OK);
		} catch (RuntimeErrorException e) {
			System.out.println(e.getMessage());
			return new ResponseEntity<Void>(headers, HttpStatus.NOT_ACCEPTABLE);
		}

	}

Olá @cido18,

Já passei por esse mesmo problema, minha sugestão é você remover a anotação @JsonDeserialize em:

Pois com a dependência:

Já faz isso autômatico.

Então, adicione essa classe no ciclo de vida de injeção de dependência do Jackson que resolve seu problema

https://gist.github.com/emanuelbatista/7996512a728bdc7ef5510214979ce386

Obrigado pela resposta, mas ao adicionar o classe o os objetos passados na função estão vindo nulos, você teve o mesmo problema?

Olá @cido18

Não tive o mesmo problema, mas posso ajudar com esse problema.

Antes de você adicionar essa nova classe esses parâmetros funcionavam na chamada ao Web Service?

Não, pois ao enviar os dados do front para para a API mostrava o erro que citei no inicio do tópico.

Ok.

Você adicionou os GET e SET no objeto Agenda.java, pois o problema pode ser esse?

Adicionei sim. Segue a classe.

@Entity
public class Agenda {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	@OneToOne
	@JoinColumn(name="doador_id")
	@NotNull
	private Doador doador;
	@Enumerated(EnumType.STRING)
	@NotBlank
	private StatusAgenda statusAgenda;
	@OneToOne
	@JoinColumn(name="laboratorio_id")
	@NotNull
	private Laboratorio laboratorio;
	@JsonFormat(pattern = "dd-MM-yyyy HH:mm:ss")
	@DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
	@NotNull
	private LocalDateTime date;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Doador getDoador() {
		return doador;
	}

	public void setDoador(Doador doador) {
		this.doador = doador;
	}

	public Laboratorio getLaboratorio() {
		return laboratorio;
	}

	public void setLaboratorio(Laboratorio laboratorio) {
		this.laboratorio = laboratorio;
	}

	public LocalDateTime getDate() {
		return date;
	}

	public void setDate(LocalDateTime date) {
		this.date = date;
	}

	public StatusAgenda getStatusAgenda() {
		return statusAgenda;
	}

	public void setStatusAgenda(StatusAgenda statusAgenda) {
		this.statusAgenda = statusAgenda;
	}

	@Override
	public String toString() {
		return "Agenda [id=" + id + ", doador=" + doador + ", statusAgenda=" + statusAgenda + ", laboratorio="
				+ laboratorio + ", date=" + date + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((date == null) ? 0 : date.hashCode());
		result = prime * result + ((doador == null) ? 0 : doador.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((laboratorio == null) ? 0 : laboratorio.hashCode());
		result = prime * result + ((statusAgenda == null) ? 0 : statusAgenda.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Agenda other = (Agenda) obj;
		if (date == null) {
			if (other.date != null)
				return false;
		} else if (!date.equals(other.date))
			return false;
		if (doador == null) {
			if (other.doador != null)
				return false;
		} else if (!doador.equals(other.doador))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (laboratorio == null) {
			if (other.laboratorio != null)
				return false;
		} else if (!laboratorio.equals(other.laboratorio))
			return false;
		if (statusAgenda != other.statusAgenda)
			return false;
		return true;
	}

}

Tente o seguinte:

  • Remover a anotação - [quote=“cido18, post:1, topic:336749”]
    @DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
    [/quote]

  • Atualizar a anotação [quote=“cido18, post:1, topic:336749”]
    @JsonFormat(pattern = “dd-MM-yyyy HH:mm:ss”)
    [/quote]

por

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy HH:mm:ss")

Olá @emanuelbatista,

Desculpe a demora. Ainda não consegui resolver, mas pelos meus teste ao adicionar a @Configuration os dados passados para minha API são anulados. Será que não está faltando nenhum outro jar?

Faça o teste no seu proprio main, usando object mapper com o register do localdate para serializar/deserializar.

Meu caro @cido18

Segue esse tutorial -> https://blog.oio.de/2015/06/13/add-support-for-java-8-date-time-api-to-jackson-serialized-rest-web-services/

Que você vai conseguir resolver seu problema referente a conversão de datas do Java 8.

Obrigado pela ajuda @igomes e @emanuelbatista

O problema no caso era os dados vindos do front corrigido isso resolvi a questão da conversão na seguinte maneira:

@Configuration
public class JacksonConfiguration {

@Autowired
private void registerSerializersDeserializers(List<ObjectMapper> objectMappers) {
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
    simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
    objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
}

}