2012-04-05 2 views
12

Я использую библиотеку Gson для преобразования объектов Java в ответ Json ... проблема заключается в том, что после запросов JPA объект, извлеченный из БД, не может быть преобразован из-за рекурсивного отношения с другими объектами (see my previous question), например:Самый простой способ удалить двунаправленные рекурсивные отношения?

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; 

Мой исходный код:

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

Как вы можете видеть, здесь я сделал:

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

только для того, чтобы убить рекурсивные отношения, установив нуль для каждого объекта GPS в списке координаторов.

По-вашему, это хорошее решение или есть ли другой метод более практичным? Спасибо

ответ

25

Существует расширение Gson под названием GraphAdapterBuilder, которое может сериализовать объекты, содержащие круглые ссылки. Вот очень упрощенный пример из соответствующего теста:

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

Это печатает:

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

Обратите внимание, что класс GraphAdapterBuilder является не включены в gson.jar. Если вы хотите использовать его, вам придется вручную его скопировать в свой проект.

+1

Спасибо! Это был спасатель при работе в спящем режиме. Сэкономил мне массу проблем при преобразовании объекта спящего режима с использованием gson. – Knubo

+0

работает и на андроиде. –

+3

, который содержит этот класс GraphAdapterBuilder? – pavan

2

Я не знаю о Гсоне, но я работаю с Джексоном. Найдите пример использования класса ObjectMapper. Что касается рекурсии, используйте @JsonManagedReference и @JsonBackReference, чтобы остановить это. Посмотрите их, например, на использование.

1

Вы можете использовать @Expose (serialize = false), чтобы избежать сериализации коллекции.

0

использовать переходных для игнорирования @OneToMany наборы для google.gson