2012-04-05 2 views
12

Uso la libreria Gson per convertire oggetti Java in una risposta JSON ... il problema è che dopo una richiesta JPA l'oggetto recuperato da DB non può essere convertito a causa di una relazione ricorsiva con altre entità (see my previous question) ad esempio:Il modo più semplice per rimuovere le relazioni ricorsive bidirezionali?

public class Gps implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @Basic(optional = false) 
    @Column(name = "IMEI", nullable = false, length = 20) 
    private String imei; 
    //some code here... 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "gpsImei", fetch = FetchType.LAZY) 
    private List<Coordonnees> coordonneesList; 


public class Coordonnees implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "IDCOORDONNEES", nullable = false) 
    private Integer idcoordonnees; 
    //some code here... 
    @JoinColumn(name = "GPS_IMEI", referencedColumnName = "IMEI", nullable = false) 
    @ManyToOne(optional = false, fetch = FetchType.LAZY) 
    private Gps gpsImei; 

mio codice sorgente:

EntityManagerFactory emf=Persistence.createEntityManagerFactory("JavaApplication21PU"); 
    GpsJpaController gjc=new GpsJpaController(emf); 

    Gps gps=gjc.findGps("123456789"); 

    for(int i=0;i<gps.getCoordonneesList().size();i++){ 
    gps.getCoordonneesList().get(i).setGpsImei(null); 
    } 

    Gson gson=new Gson(); 
    String json=gson.toJson(gps);//convert to json response 

    System.out.println(json); 

Come si può vedere qui ho fatto:

for(int i=0;i<gps.getCoordonneesList().size();i++){ 
    gps.getCoordonneesList().get(i).setGpsImei(null); 
    } 

solo per uccidere la relazione ricorsiva impostando null per ogni oggetto GPS nella coordonneesList ..

Secondo la vostra opinione questa è una buona soluzione oppure esiste un altro metodo più pratico? Grazie

risposta

25

C'è un'estensione di Gson chiamata GraphAdapterBuilder che può serializzare oggetti che contengono riferimenti circolari. Ecco un esempio molto semplificato dal banco di prova corrispondente:

Roshambo rock = new Roshambo("ROCK"); 
Roshambo scissors = new Roshambo("SCISSORS"); 
Roshambo paper = new Roshambo("PAPER"); 
rock.beats = scissors; 
scissors.beats = paper; 
paper.beats = rock; 

GsonBuilder gsonBuilder = new GsonBuilder(); 
new GraphAdapterBuilder() 
    .addType(Roshambo.class) 
    .registerOn(gsonBuilder); 
Gson gson = gsonBuilder.create(); 
System.out.println(gson.toJson(rock)); 

Questo stampa:

{ 
    '0x1': {'name': 'ROCK', 'beats': '0x2'}, 
    '0x2': {'name': 'SCISSORS', 'beats': '0x3'}, 
    '0x3': {'name': 'PAPER', 'beats': '0x1'} 
} 

Nota che la classe GraphAdapterBuilder è non incluso nel gson.jar. Se vuoi usarlo, dovrai copiarlo manualmente nel tuo progetto.

+1

Grazie! Questo è stato un vero toccasana quando si lavora con l'ibernazione. Mi ha risparmiato un sacco di problemi durante la conversione di un'entità di ibernazione usando gson. – Knubo

+0

funziona anche su Android. –

+3

quale jar contiene questa classe "GraphAdapterBuilder"? – pavan

2

Non so con Gson ma sto lavorando con Jackson. Cerca un esempio di utilizzo della sua classe ObjectMapper. Per quanto riguarda la ricorsione, usa @JsonManagedReference e @JsonBackReference per fermarlo. Osservali anche per esempio.

1

È possibile utilizzare @Expose (serialize = false) per evitare che la raccolta venga serializzata.

0

Usa transitoria per ignorare @OneToMany set per google.gson