php editor Zimo brings you solutions to problems when Java deserializes LocalDateTime. When using the Jackson library for deserialization, you sometimes encounter an InvalidFormatException exception, especially when dealing with the LocalDateTime type. This article will introduce the cause and solution of this problem in detail to help you successfully solve this common deserialization exception.
I have a problem deserializing localdatetime in a spring boot application. Below is the relevant code.
front end:
update(lancamento: lancamento): promise<lancamento> { const headers = new httpheaders() .set('authorization', this.chave) .set('content-type', 'application/json'); this.conversordedata([lancamento]); return firstvaluefrom(this.http.put<any>(`${this.url}/${lancamento.codigo}`, lancamento, { headers })); } findbycode(codigo: number): promise<lancamento> { const headers = new httpheaders() .set('authorization', this.chave); return this.http.get(`${this.url}/${codigo}`, { headers }) .topromise() .then((response: any) => { const lancamento = response as lancamento; this.conversordedata([lancamento]); return lancamento; }) .catch((error: any) => { console.error('erro ao buscar lançamento por código: ', error); throw error; }); } //se os atributos forem do tipo date conversordedata(lancamentos: lancamento[]){ for(const lancamento of lancamentos){ if(lancamento.datavencimento && isvalid(lancamento.datavencimento)){ lancamento.datavencimento = new date(format(lancamento.datavencimento, 'dd/mm/yyyy')); } if(lancamento.datapagamento && isvalid(lancamento.datapagamento)){ lancamento.datapagamento = new date(format(lancamento.datapagamento, 'dd/mm/yyyy')); } } }
Backend: lancamento Class:
package com.algaworks.algamoney_api.domain.model; import com.fasterxml.jackson.annotation.jsonformat; import jakarta.persistence.*; import jakarta.validation.constraints.notnull; import org.springframework.format.annotation.datetimeformat; import java.math.bigdecimal; import java.time.localdate; import java.time.localdatetime; import java.util.objects; @entity @table(name = "lancamento") public class lancamento { @id @generatedvalue(strategy = generationtype.identity) private integer codigo; @notnull private string descricao; @column(name = "data_vencimento") @jsonformat(pattern = "dd/mm/yyyy") private localdatetime datavencimento; @column(name = "data_pagamento") @jsonformat(pattern = "dd/mm/yyyy") private localdatetime datapagamento; @notnull private bigdecimal valor; private string observacao; @notnull @enumerated(enumtype.string) private tipolancamento tipo; @notnull @manytoone // vários lançamentos podem estar em uma categoria @joincolumn(name = "codigo_categoria") private categoria categoria; @notnull @manytoone @joincolumn(name = "codigo_pessoa") private pessoa pessoa; public integer getcodigo() { return codigo; } public void setcodigo(integer codigo) { this.codigo = codigo; } public string getdescricao() { return descricao; } public void setdescricao(string descricao) { this.descricao = descricao; } public localdatetime getdatavencimento() { return datavencimento; } public void setdatavencimento(localdatetime datavencimento) { this.datavencimento = datavencimento; } public localdatetime getdatapagamento() { return datapagamento; } public void setdatapagamento(localdatetime datapagamento) { this.datapagamento = datapagamento; } public bigdecimal getvalor() { return valor; } public void setvalor(bigdecimal valor) { this.valor = valor; } public string getobservacao() { return observacao; } public void setobservacao(string observacao) { this.observacao = observacao; } public tipolancamento gettipo() { return tipo; } public void settipo(tipolancamento tipo) { this.tipo = tipo; } public categoria getcategoria() { return categoria; } public void setcategoria(categoria categoria) { this.categoria = categoria; } public pessoa getpessoa() { return pessoa; } public void setpessoa(pessoa pessoa) { this.pessoa = pessoa; } @override public boolean equals(object o) { if (this == o) return true; if (o == null || getclass() != o.getclass()) return false; lancamento that = (lancamento) o; return codigo.equals(that.codigo); } @override public int hashcode() { return objects.hash(codigo); } }
resumolancamento Class:
package com.algaworks.algamoney_api.repository.projection; import com.algaworks.algamoney_api.domain.model.tipolancamento; import java.math.bigdecimal; import java.time.localdate; import java.time.localdatetime; /** * 7.1. implementando projeção de lançamento*/ public class resumolancamento { private integer codigo; private string descricao; private localdatetime datavencimento; private localdatetime datapagamento; private bigdecimal valor; private tipolancamento tipo; private string categoria; private string pessoa; public resumolancamento(integer codigo, string descricao, localdatetime datavencimento, localdatetime datapagamento, bigdecimal valor, tipolancamento tipo, string categoria, string pessoa) { this.codigo = codigo; this.descricao = descricao; this.datavencimento = datavencimento; this.datapagamento = datapagamento; this.valor = valor; this.tipo = tipo; this.categoria = categoria; this.pessoa = pessoa; } public integer getcodigo() { return codigo; } public void setcodigo(integer codigo) { this.codigo = codigo; } public string getdescricao() { return descricao; } public void setdescricao(string descricao) { this.descricao = descricao; } public localdatetime getdatavencimento() { return datavencimento; } public void setdatavencimento(localdatetime datavencimento) { this.datavencimento = datavencimento; } public localdatetime getdatapagamento() { return datapagamento; } public void setdatapagamento(localdatetime datapagamento) { this.datapagamento = datapagamento; } public bigdecimal getvalor() { return valor; } public void setvalor(bigdecimal valor) { this.valor = valor; } public tipolancamento gettipo() { return tipo; } public void settipo(tipolancamento tipo) { this.tipo = tipo; } public string getcategoria() { return categoria; } public void setcategoria(string categoria) { this.categoria = categoria; } public string getpessoa() { return pessoa; } public void setpessoa(string pessoa) { this.pessoa = pessoa; } }
question:
com.fasterxml.jackson.databind.exc.invalidformatexception: Unable to deserialize from string '10/01/2024' Value of type java.time.localdatetime
: Unable to deserialize java. time.localdatetime: (java.time.format .datetimeparseexception) Unable to parse text '10/01/2024': Unable to get localdatetime from temporalaccessor: {}, iso parsed as 2024-01-10 of type java.time.format.parsed
In [Source: (org.springframework.util.streamutils$nonclosinginputstream); line: 1, column: 63] (via reference chain: com.algaworks.algamoney_api.domain.model.lancamento["datavencimento"])
In console.log() of lancamentos, the format of the attributes "datavencimento" and "datapagamento" is "dd/mm/yyyy".
I suspect there is a date format issue during deserialization. Despite updating the frontend and backend code, the problem persists. I believe the problem is with the client, I don't know.
Any guidance or suggestions would be greatly appreciated. Thanks!
I did everything with dataconverter() method but still no success.
conversorDeData(lancamentos: Lancamento[]){ for(const lancamento of lancamentos){ if(lancamento.dataVencimento && isValid(lancamento.dataVencimento)){ lancamento.dataVencimento = new Date(format(lancamento.dataVencimento, 'dd/MM/yyyy')); } if(lancamento.dataPagamento && isValid(lancamento.dataPagamento)){ lancamento.dataPagamento = new Date(format(lancamento.dataPagamento, 'dd/MM/yyyy')); } } }
To resolve this issue, you can do one of the following:
Option 1: Adjust json date format Change the date format in the json payload to match the pattern "yyyy-mm-ddthh:mm:ss" or any format directly compatible with localdatetime. For example:
{ "codigo": 1, "descricao": "sample description", "datavencimento": "2024-01-10t00:00:00", "datapagamento": "2024-01-10t00:00:00", "valor": 100.0, "observacao": "sample observation", "tipo": "sample_type", "categoria": { "codigo": 1 }, "pessoa": { "codigo": 1 } }
Option 2: Use @jsondeserialize to specify a custom deserialization format You can annotate the localdatetime field in the lancamento class with @jsondeserialize to specify a custom deserialization format. For example:
import com.fasterxml.jackson.databind.annotation.jsondeserialize; import com.fasterxml.jackson.datatype.jsr310.deser.localdatetimedeserializer; // other imports... @entity @table(name = "lancamento") public class lancamento { // ... other fields @column(name = "data_vencimento") @jsondeserialize(using = localdatetimedeserializer.class) private localdatetime datavencimento; @column(name = "data_pagamento") @jsondeserialize(using = localdatetimedeserializer.class) private localdatetime datapagamento; // ... other methods }
Remember to adjust the deserialization format or date format in the json payload to ensure they are properly aligned. Choose the method that best suits your requirements and coding practices.
Option 3: This problem occurs because localdatetime in java does not have a direct formatter for the pattern "dd/mm/yyyy" containing date and time components. If you are only interested in the date component, you may need to change the type of these fields to localdate.
//... @Column(name = "data_vencimento") @JsonFormat(pattern = "dd/MM/yyyy") private LocalDate dataVencimento; @Column(name = "data_pagamento") @JsonFormat(pattern = "dd/MM/yyyy") private LocalDate dataPagamento; //... public LocalDate getDataVencimento() { return dataVencimento; } public void setDataVencimento(LocalDate dataVencimento) { this.dataVencimento = dataVencimento; } public LocalDate getDataPagamento() { return dataPagamento; } public void setDataPagamento(LocalDate dataPagamento) { this.dataPagamento = dataPagamento; }
The above is the detailed content of Problem deserializing LocalDateTime: Jackson InvalidFormatException. For more information, please follow other related articles on the PHP Chinese website!