2012-07-02 5 views
0

J'utilise Hibernate 4.1 et Spring 3.1. Considérons la classe User suivante ayant des références à un autre objet, y compris self. Tous les mappings d'hibernation que j'ai définis sont LAZY donc je chargerai les objets de référence seulement quand je les utiliserai dans le jsp ou le code else où.Modèle de domaine vers JSON - problème de sérialisation profonde

class User { 
    private User createdBy; 
    private Department department; 
    private Project project; 
    ..... 
    ..... 
} 

Le problème est quand je veux retourner une représentation JSON où il utilise la réflexion pour le faire et il en fait une sérialisation profonde. Voici mon code de contrôleur.

@ResponseBody 
public User getUser(int id) { 
    User user = [fetch user from service]; 
    return user; 
} 

Puisque j'ai auto-référence aussi, il va en boucle infinie.

Quelle est la solution pour résoudre ce problème? Je sais que j'ai besoin d'utiliser un pattern DTO où je renvoie un UserDTO à la place, mais combien de méthodes je crée. Par exemple, à un endroit j'ai juste besoin des attributs d'utilisateur de base, à l'autre endroit où j'ai besoin d'utilisateur et de son département, à l'autre endroit j'ai besoin d'utilisateur avec le département et le projet.

Combien de méthodes aurais-je besoin d'exposer? Y a-t-il un autre moyen de résoudre ce problème?

+0

Quelle bibliothèque JSON utilisez-vous? – nobeh

+0

Vous pouvez créer des objets DTO à structure plate pour chaque cas avec les champs requis de Emp, Proj et Dep. – JMelnik

+0

J'utilise org.codehaus.jackson –

Répondre

1

Le problème est que vous avez une référence circulaire et que votre codeur JSON ne la gère pas. Donc, vous devez le gérer manuellement.

Créer un DTO tel que vous l'avez commenté serait utile. Vous pouvez implémenter un assistant avec une méthode pour chaque niveau de décodage dont vous avez besoin.

Vous pouvez utiliser BeanUtils pour copier chaque propriété d'un bean à l'autre.

Une autre solution (un peu plus conceptuelle) serait:

Mettre en oeuvre une sorte de décorateur pour chaque méthode limite et appliquer dozer sur le résultat. Un exemple, vous pouvez prendre here

La Décoration se produit plus ou moins comme ceci:

public interface Controller { 
    User getUser(int id); 
} 

public class RealController { 
    public User getUser(int id) { 
     return dao.getUser(id); 
    } 
} 

public class DecoratedController { 

    private Controller realController; 

    public User getUser(int id) { 
     // here you will apply dozer or do it manually creating an object with so deep as you wish 
     return flatUserStructure(realController.getUser(id)); 
    } 
} 
0

Pour être en mesure de régler le chargement de l'association Mise en veille prolongée, vous pouvez utiliser chercher rejoindre, s'il vous plaît lire 14.3. Associations and joins

Pour éviter les problèmes de sérialisation profonde, vous pouvez créer des DTO appropriés et les affiner avec quelque chose comme l'annotation @JsonIgnore du projet Jackson Java JSON-processor.

0

Je pense que le problème se compose de deux parties:

sérialisation JSON personnalisé: Vous pouvez utiliser cette approche pour éviter de définir plusieurs UserDTO s pour User. Toutefois, il reste que vous devez probablement définir le sérialiseur JSON en tant que bean ou un objet de service configurable de sorte que vous pouvez lui commander quoi sérialiser dans différentes mappages de méthode de contrôleur. Un bon exemple peut être trouvé here.

Configuration du ressort: L'étape suivante consiste à configurer le ressort pour utiliser le sérialiseur JSON de votre client.Ainsi, en utilisant @ResponseBody, Spring utilisera votre sérialiseur JSON personnalisé. De bons exemples peuvent être trouvés here et there.

Questions connexes