2014-09-18 16 views
6

Ho un'entità:jackson - non serializzare oggetti pigre

@Entity 
public class Book { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    @Column 
    private String title; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL) 
    private List<Genre> genre; 

} 

poi ho un controller il cui scopo è quello di recuperare i libri, il mio problema è che, il campo di genere viene incluso nella risposta JSON di il mio controller In qualsiasi modo posso escludere quei campi che sono pigri carichi quando serializza l'oggetto?

Questa è la configurazione del mio ObjectMapper:

Hibernate4Module hm = new Hibernate4Module(); 
hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false); 
registerModule(hm); 
configure(SerializationFeature.INDENT_OUTPUT, true); 

Grazie!

Non riesco a contrassegnarlo come JsonIgnore, poiché sarà per sempre fuori dalla scatola di serializzazione. Ci saranno momenti in cui avrò bisogno di recuperare i generi insieme al libro, e per allora userò "fetch join" sulla mia query in modo che non sia nullo.

+0

[Transient] [1] [1]: http://stackoverflow.com/ questions/20700530/why-use-transient-keyword-in-java Prova a utilizzare questo argomento per ottenere il tuo interesse;) – Fincio

+0

Ciao @Fincio, non posso rendere il campo di genere come transitorio, in quanto ne ho bisogno è persistente sul Banca dati. – lorraine

+0

Hmmm, che dire di @JsonIgnoreProperties ({"genere"}) o @JsonIgnore – Fincio

risposta

7

È possibile eseguire questa operazione con l'annotazione Jackson @JsonInclude.

In base allo latest version's javadoc (2.4 right now) è possibile specificare con una semplice annotazione se includere o meno la proprietà annotata se il valore del campo è nullo o vuoto.

Per impostazione predefinita, è JsonInclude.Include.ALWAYS e questo significa che anche se i valori pigramente non caricati sono nulli, Jackson include la proprietà.

specificare di non includere i valori vuoti o nulli in grado di ridurre notevolmente le dimensioni della risposta JSON, con tutti i benefici inclusi ..

Se si desidera modificare questo comportamento, è possibile aggiungere l'annotazione in classe -level o singola proprietà/livello getterMethod.

tenta di aggiungere le seguenti annotazioni per i campi che non si desidera includere se vuota:

@JsonInclude(JsonInclude.Include.NON_EMPTY) 
@OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL) 
private List<Genre> genre; 
+2

Questo non funziona per me in una soluzione Spring JPA + Spring REST Controller. Il recupero pigro si verifica ancora quando avviene la serializzazione JSON ... –

+0

Questa non è la risposta giusta per JPA 2.1 in combinazione con EclipseLink! Il problema è ovviamente che Jackson controlla le proprietà di "NON_EMPTY" chiamando i getter e che fa scattare il Lazy Loading! Sfortunatamente, non vi è alcun AccesType "Field" Json Annotation o così, sarebbe di aiuto. Questo è supportato da Moxy, penso (penso che usi le annotazioni JAXB per questo). – Nabi

+0

@RonyeVernaes funziona per me dopo aver aggiunto un bean 'Hibernate5Module'. Vedere la risposta di chrismarx in http://stackoverflow.com/questions/21708339/avoid-jackson-serialization-on-non-fetched-lazy-objects. – Zeemee

1

Forse questo è relativo a a known issue about lazy loading.

Non utilizzo jackson-datatype-hibernate, ma quello che ho fatto per risolvere lo stesso problema è ottenere la raccolta persistente dall'immagine usando un DTO invece di serializzare direttamente un oggetto Hibernate. Strumenti come Dozer possono aiutarti in questo. In alternativa, c'è un small utility che ho scritto per fare mappature come questa.

Se si desidera solo sperimentare come potrebbe essere un DTO, è possibile sostituire la raccolta persistente non caricata con una raccolta vuota normale, ad esempio books.setGenre (nuova ArrayList <>()); Sfortunatamente non conosco un modo per capire se un oggetto caricato pigramente è stato caricato o meno, quindi non è possibile effettuare automaticamente questa riassegnazione. Le posizioni in cui si sostituiscono le raccolte persistenti dovrebbero essere determinate dall'utente caso per caso.

2

È possibile utilizzare Jackson's JSON Filter Feature:

@Entity 
@JsonFilter("Book") 
public class Book { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    @Column 
    private String title; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL) 
    private List<Genre> genre; 
} 

@Entity 
@JsonFilter("Genre") 
public class Genre { 
    ... 
} 

Poi nel controller di specificare cosa filtrare:

@Controller 
public class BookController { 
     @Autowired 
     private ObjectMapper objectMapper; 

     @Autowird 
     private BookRepository bookRepository; 

     @RequestMapping(value = "/book", method = RequestMethod.GET, produces = "application/json") 
     @ResponseBody 
     public ResponseEntity<String> getBooks() { 

      final List<Book> books = booksRepository.findAll(); 
      final SimpleFilterProvider filter = new SimpleFilterProvider(); 
      filter.addFilter("Book", SimpleFilterProvider.serializeAllExcept("Genre"); 
      return new ResponseEntity<>(objectMapper.writer(filter).writeValueAsString(books), HttpStatus.OK) 
     } 

} 

In questo modo, è possibile controllare quando si desidera filtrare il rapporto pigro in fase di esecuzione

+0

Ora che la coda di modifica è piena, dovrei correggere una riga; il secondo argomento di addFilter() dovrebbe essere ** SimpleBeanPropertyFilter **. serializeAll ... not ** SimpleFilterProvider **. serializeAll ... classe –

Problemi correlati