问题反序列化 LocalDateTime:Jackson InvalidFormatException

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

我在 Spring Boot 应用程序中反序列化 LocalDateTime 时遇到问题。下面是相关代码。

前端:

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'));
    }

  }
}

后端:Lancamento 类:

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);
    }
}

兰卡门托课程简介:

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;
    }
}

问题:

com.fasterxml.jackson.databind.exc.InvalidFormatException:无法从字符串“10/01/2024”反序列化

java.time.LocalDateTime
类型的值:无法反序列化java.time.LocalDateTime:(java.time.format.DateTimeParseException)文本无法解析“10/01/2024”:无法从 TemporalAccessor 获取 LocalDateTime:{},ISO 解析为 java.time.format.Parsed 类型的 2024-01-10 在[来源:(org.springframework.util.StreamUtils$NonClosingInputStream);行:1,列:63](通过参考链:com.algaworks.algamoney_api.domain.model.Lancamento[“dataVencimento”])

在lancamentos的console.log()中,属性“dataVencimento”和“dataPagamento”的格式为“dd/MM/yyyy”。

我怀疑反序列化期间存在日期格式问题。尽管更新了前端和后端代码,问题仍然存在。我相信问题出在客户身上,我不知道。

  1. 在 Spring Boot 应用程序中从字符串反序列化 LocalDateTime 时,如何修复 InvalidFormatException?
  2. 正确的 LocalDateTime 序列化和反序列化是否需要特定的配置或调整?

如有任何指导或建议,我们将不胜感激。谢谢!

我用 Dataconverter() 方法做了所有事情,但仍然没有成功。

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'));
    }

  }
}
java date
1个回答
0
投票

要解决此问题,您可以执行以下操作之一:

选项1:调整JSON日期格式 更改 JSON 负载中的日期格式以匹配模式“yyyy-MM-ddTHH:mm:ss”或与 LocalDateTime 直接兼容的任何格式。例如:

{
  "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
  }
}

选项2:使用@JsonDeserialize指定自定义反序列化格式 您可以使用 @JsonDeserialize 注释 Lancamento 类中的 LocalDateTime 字段,以指定自定义反序列化格式。例如:

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
}

请记住调整 JSON 负载中的反序列化格式或日期格式,以确保它们正确对齐。选择最适合您的要求和编码实践的方法。

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