2012-01-27 22 views
24

ho rapporto bi-direzionale come questo ...Spring MVC - JSON ricorsione infinita

Person.java

public class Person{ 

    @JsonIgnore 
    @OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL, 
     fetch=FetchType.EAGER, mappedBy="person") 
    private Set<PeopleOrg> organization; 
    ..... 
} 

PersonOrganization.java

public class PersonOrganization{ 

    @JsonIgnore 
@ManyToOne(fetch=FetchType.LAZY) 
@JoinColumn(name="PERSONID", nullable=false) 
private Person person; 
    } 

Anche con @JsonIgnore annotazione Sono ottenendo un errore di ricorsione infinito durante il tentativo di recuperare i record Person. Ho provato nuove annotazioni nella versione 1.6. @JsonBackReference e @JsonManagedReference. Anche allora io sono sempre ricorsione infinita ..

Con @JsonBackReference("person-organization") su Person e @JsonManagedReference("person-organization") su PersonOrganization

org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]->com.entity.PersonOrganization["person"]->com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]... 

Anche se io intercambiare le annotazioni, ancora sto ottenendo questa eccezione .. Per favore fatemi sapere se v'è qualcosa di sbagliato con le mappature o il modo in cui sto usando le annotazioni JSON. Grazie

risposta

38

Mi sono imbattuto in questo prima. Ma dopo aver spostato @JsonIgnore da campo privato a getter del campo, la ricorsione infinita è scomparsa. Quindi la mia ipotesi è che @JsonIgnore potrebbe non funzionare in campo privato. Tuttavia, javadoc o tutorial del processore Jackson JSON di Java non ne parlano, quindi non posso essere sicuro al 100%. Solo per tua informazione.

+2

Questo ha funzionato anche per me, ma non riesco a scoprire perché! – Skurpi

+2

Potrei darti un grosso bacio in questo momento. Questo ha risolto il mio problema. Nel mio caso, il campo era protetto. – theblang

+0

Non è abbastanza, ho ancora il problema. –

10

Il seguente collegamento indica che è necessario annotare il metodo utilizzato dallo strumento JSON per attraversare il grafico dell'oggetto, in modo da ignorare l'attraversamento.

http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/annotate/JsonIgnore.html

Nel mio caso ho due oggetti collegati come questo prodotto < -> productimage. Così JSON parser è andato in un ciclo infinito con fuori l'annotazione @JsonIgnore sul seguente per ottenere metodi

@JsonIgnore 
public Product getImageOfProduct() { 
    return imageOfProduct; 
} 

in productimage e

@JsonIgnore 
public Set<ProductImage> getProductImages() { 
    return productImages; 
} 

nel prodotto.

Con l'annotazione, le cose funzionano correttamente.

+0

Annotare il getter invece del campo ha funzionato per me. ERA 8.5 JEE 6. –

5

So che questa domanda non riguarda specificamente Spring Data REST, ma ho eseguito questa eccezione nel contesto di Spring Data REST e volevo condividere il problema. Ho avuto una relazione bidirezionale che coinvolge un'entità senza repository. La creazione del repository ha fatto sparire il ciclo.

+0

Ho entrambi i repository, ma ho ancora il ciclo –

+1

Ho trovato la soluzione: dobbiamo usare @ JsonManagedReference e @ JsonBackReference sulle Proiezioni (NON nelle entititi) –

4

Dal momento che Jackson 1.6 è possibile utilizzare due annotazioni per risolvere il problema della ricorsione infinita senza ignorare i getter/setter durante la serializzazione: @JsonManagedReference e @JsonBackReference.

Per maggiori dettagli fare riferimento https://stackoverflow.com/a/18288939/286588

0

Questo potrebbe essere po 'vecchio ma è possibile aggiungere @JsonIgnore a livello di classe con tutte le proprietà che dovrebbe ignorare. e.g

@JsonIgnore("productImaes","...") 
public class Product{ ... 
} 
0

volte il campo membro può avere riferimento interno allo stesso tipo di classe di per sé, che potrebbe causare infinito ricorsione quando toJson.

E.g .: si dispone di un campo membro Klass a, mentre la definizione di classe di tale Klass è la seguente.

class Klass { 
    Klass mySibling; 

    public toString() { 
     return "something" + mySibling.whateverMethod; 
    } 
} 

Soluzione: refactor il campo membro, eliminare il riferimento interno.

-2

Jackson lavora su Reflection chiamando getter. Anch'io ho avuto una situazione in cui avevo un getter dello stesso oggetto all'interno della sua classe. Jackson è andato in una infinita ricorsione mentre mangiava pila ripetutamente chiamando il suo getter. Getter rimosso, quindi risolto.

Il mio consiglio: Il mio consiglio: Se si desidera utilizzare jackson per la conversione di un oggetto, non mantenere mai i getter che fanno riferimento allo stesso oggetto, come nel caso di singleton.

0

Apparentemente da Jackson 1.6 è possibile utilizzare @JsonManagedReference e @JsonBackReference per risolvere efficacemente il problema di ricorsione infinito.

Non entrerò nei dettagli, ma questo cambiamento di classi nel formato seguente dovrebbe risolvere il problema.

public class Person{ 

    @OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="person") 
    @Column(nullable = true) 
    @JsonManagedReference 
    private Set<PeopleOrg> organization; 
    ..... 
} 

public class PersonOrganization{ 

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name="PERSONID") 
    @JsonBackReference 
    private Person person; 
    } 

Fondamentalmente Jackson converte Set<PeopleOrg> organization, la parte anteriore del riferimento un formato json simile utilizzando il processo di smistamento, sembra poi per Person person, la parte posteriore del riferimento e non serializza esso.

Credits - Kurt Bourbaki & Maggiori informazioni - http://keenformatics.blogspot.co.ke/2013/08/how-to-solve-json-infinite-recursion.html

0

Questa eccezione è dovuto al fatto, il vostro campo costruttore non sono corretto, si prega di controllare le proprietà costruttori ancora una volta nelle vostre classi, e controllare la mappatura dare correttamente o meno,

mantenere le due Costruttori, prima è pari a zero costruzione e secondo costruttore è con i campi ed entrambi dovrebbero essere contenere il super

1

Se A ha B & B ha A.

Questo è rapporto uno a uno, ma che forma una relazione circolare.

In qualsiasi classe, utilizzare l'annotazione di JustIgnore.

class A 
{  
B b;  
} 

class B 
{  
@JsonIgnore 
A a; 
} 

Questo vale anche per altri rapporti come uno a molti.