Maison > Java > le corps du texte

Problème de désérialisation de LocalDateTime : Jackson InvalidFormatException

王林
Libérer: 2024-02-22 13:58:06
avant
365 Les gens l'ont consulté

L'éditeur PHP Zimo vous apporte une solution au problème lorsque Java désérialise LocalDateTime. Lorsque vous utilisez la bibliothèque Jackson pour la désérialisation, vous rencontrez parfois une exception InvalidFormatException, notamment lorsqu'il s'agit du type LocalDateTime. Cet article présentera en détail la cause et la solution de ce problème pour vous aider à résoudre avec succès cette exception de désérialisation courante.

Contenu de la question

J'ai un problème pour désérialiser localdatetime dans une application Spring Boot. Vous trouverez ci-dessous le code correspondant.

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

  }
}
Copier après la connexion

Backend : lancamento Classe :

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);
    }
}
Copier après la connexion

resumolancamento Catégorie :

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;
    }
}
Copier après la connexion

Question :

com.fasterxml.jackson.databind.exc.invalidformatexception : Impossible de désérialiser à partir de la chaîne "10/01/2024" Valeur de type java.time.localdatetime : Impossible de désérialiser java.time.localdatetime : (java.time.format .datetimeparseexception ) Impossible de analyser le texte "10/01/2024" : Impossible d'obtenir l'heure locale à partir de l'accesseur temporel : {}, iso analysé comme 2024-01-10 de type java.time.format.parsed Dans [Source : (org.springframework.util.streamutils$nonclosinginputstream) ; ligne : 1, colonne : 63] (via la chaîne de référence : com.algaworks.algamoney_api.domain.model.lancamento["datavencimento"])

Dans console.log() des lancamentos, le format des attributs "datavencimento" et "datapagamento" est "jj/mm/aaaa".

Je soupçonne qu'il y a un problème de format de date lors de la désérialisation. Malgré la mise à jour du code frontend et backend, le problème persiste. Je pense que le problème vient du client, je ne sais pas.

  1. Comment corriger l'exception de format invalide lors de la désérialisation de la datetime locale à partir d'une chaîne dans l'application Spring Boot ?
  2. La sérialisation et la désérialisation locales datetime correctes nécessitent-elles une configuration ou un réglage spécifique ?

Tout conseil ou suggestion serait grandement apprécié. Merci!

J'ai tout fait avec la méthode dataconverter() mais toujours sans succès.

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

  }
}
Copier après la connexion

Solution de contournement

Pour résoudre ce problème, vous pouvez effectuer l'une des opérations suivantes :

Option 1 : Ajuster le format de date json Modifiez le format de date dans la charge utile json pour qu'il corresponde au modèle "aaaa-mm-jjjh: mm: ss" ou à tout format directement compatible avec localdatetime. Par exemple :

{
  "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
  }
}
Copier après la connexion

Option 2 : utilisez @jsondeserialize pour spécifier un format de désérialisation personnalisé Vous pouvez annoter le champ localdatetime dans la classe lancamento avec @jsondeserialize pour spécifier un format de désérialisation personnalisé. Par exemple :

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
}
Copier après la connexion

N'oubliez pas d'ajuster le format de désérialisation ou le format de date dans la charge utile json pour vous assurer qu'ils sont correctement alignés. Choisissez la méthode qui correspond le mieux à vos besoins et à vos pratiques de codage.

Option 3 : ce problème se produit car localdatetime en Java n'a pas de formateur direct pour le modèle "jj/mm/aaaa" contenant les composants de date et d'heure. Si vous n'êtes intéressé que par le composant date, vous devrez peut-être changer le type de ces champs en 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;
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!