Annotazione transitoria JPA e JSON

Questo è un seguito alla seguente domanda sull’annotazione transitoria JPA Perché JPA ha un’annotazione @Transient?

Ho una variabile transitoria che non voglio persistere ed è contrassegnata con l’annotazione transitoria. Tuttavia, quando voglio produrre JSON dal mio controller di rest, questa variabile transitoria non è disponibile nel JSON emesso.

POJO PublicationVO è semplice, senza attributi di fantasia, solo alcuni attributi privati ​​(che sono persistenti) con getter e setter e 1 variabile transitoria.

@RequestMapping(value = { "{publicationId}"}, method = RequestMethod.GET, produces = "application/json") @ResponseBody public PublicationVO getPublicationDetailsJSON(@PathVariable(value = "publicationId") Integer publicationId) { LOG.info("Entered getPublicationDetailsJSON - publicationId: " + publicationId); //Call method to get the publicationVO based on publicationId PublicationVO publicationVO = publicationServices.getPublicationByIdForRestCalls(publicationId); LOG.info("publicationVO:{}", publicationVO); LOG.info("Exiting getPublicationDetailsJSON"); return publicationVO; } 

Il PublicationVO è il seguente

  package com.trinity.domain.dao; import java.util.Calendar; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Transient; import com.fasterxml.jackson.annotation.JsonInclude; @Entity @Table(name = "publication") public class PublicationVO { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", unique = true, nullable = false) private Integer id; @Column(name = "publicationName", unique = false, nullable = false, length = 200) private String publicationName; @Column(name = "publicationSource", unique = false, nullable = false, length = 45) private String publicationSource; @Column(name = "dateAdded", unique = false, nullable = false) private Calendar dateAdded; @Transient private float percentageProcessed; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPublicationName() { return publicationName; } public void setPublicationName(String publicationName) { this.publicationName = publicationName; } public String getPublicationSource() { return publicationSource; } public void setPublicationSource(String publicationSource) { this.publicationSource = publicationSource; } public Calendar getDateAdded() { return dateAdded; } public void setDateAdded(Calendar dateAdded) { this.dateAdded = dateAdded; } public float getPercentageProcessed() { return percentageProcessed; } public void setPercentageProcessed(float percentageProcessed) { this.percentageProcessed = percentageProcessed; } @Override public String toString() { return "PublicationVO [id=" + id + ", publicationName=" + publicationName + ", publicationSource=" + publicationSource + ", dateAdded=" + dateAdded + ", percentageProcessed=" + percentageProcessed + "]"; } } 

Quando vedo l’istruzione debug per publicationVO nei miei log, la variabile transitoria è inclusa nell’output ma nel mio codice client, la variabile transitoria non è inclusa nella risposta json.

Qualsiasi aiuto è molto apprezzato.

Grazie, Damien

Contrariamente a quanto ti dicevo nei commenti, sembra che a Jackson interessino le annotazioni JPA quando vengono utilizzate per serializzare istanze di classi di entity framework grazie al modulo Hibernate di Jackson .

All’interno di quel modulo, c’è un HibernateAnnotationIntrospector a cui la documentazione si riferisce come a

semplice AnnotationIntrospector che aggiunge il supporto per l’uso di Transient per indicare campi ignorabili (insieme alle annotazioni Jackson e / o JAXB).

E come puoi vedere qui , il comportamento predefinito di Jackson è controllare qualsiasi annotazione @Transient che può trovare.

Quindi, alla fine, il tuo problema può essere risolto in uno di questi 3 modi:

  1. Configura Jackson (usando il metodo setUseTransient di HibernateAnnotationIntrospector) per disabilitare il controllo delle annotazioni @Transient (vedi questa risposta per i dettagli di implementazione).
  2. Utilizzare un object diverso da PublicationVO come risultato restituito getPublicationDetailsJSON metodo getPublicationDetailsJSON . Dovrai copiare le proprietà dal tuo object valore all’object che viene restituito a un certo punto.
  3. Rimuovere l’annotazione @Transient e mantenere la proprietà (ma vorrei capire se questa non è un’opzione per voi poiché probabilmente avete buone ragioni per aver fatto questa proprietà JPA-transient in primo luogo).

Saluti

Ho semplicemente aggiunto annotazioni JsonSerialize e JsonDeserialize .

 @Transient @JsonSerialize @JsonDeserialize private String myField; 

Giusto per aggiungere ulteriormente alla risposta fornita da m4rtin

Sono andato con il primo approccio – Configura Jackson (usando il metodo setUseTransient di HibernateAnnotationIntrospector) per disabilitare il controllo delle annotazioni @Transient.

Nel mio progetto ho dovuto seguire il seguente thread per evitare la serializzazione di jackson su oggetti pigri non recuperati Evitare la serializzazione di Jackson su oggetti pigri non recuperati

Per configurare il mio progetto in modo che non ignori le annotazioni transitori, ho impostato Hibernate4Module come segue

  Hibernate4Module hm = new Hibernate4Module(); hm.disable(Feature.USE_TRANSIENT_ANNOTATION); 

Grazie per il tuo aiuto su questo m4rtin

Io uso sia @Transient che @JsonProperty, quindi funziona!

 @Transient @JsonProperty private String mapImageSrc; 

Cosa ha funzionato per me:

 @Transient @JsonProperty 

nel GETTER (non nella definizione del campo privato)

E

 @JsonAutoDetect(fieldVisibility = Visibility.ANY) 

annotare la class

usa @JsonIgnore in com.fasterxml.jackson.annotation c’è anche @JsonFormat per la variabile Date. per me va bene

Prova @JsonView dopo aver aggiunto @Transient

Dal momento che nessuna altra soluzione qui ha funzionato per me, lasciatemi pubblicare la mia soluzione su come ha fatto il trucco per me:

 @Transient @JsonSerialize private String mapImageSrc; 

Questa sembra essere la soluzione migliore per me dato che l’annotazione @JsonSerialize è stata fatta per quel caso d’uso.