Étrange Exception Jackson étant jeté lors de la sérialisation de L'objet hiberné

Jackson lance une exception bizarre que je ne sais pas comment réparer. J'utilise Spring, Hibernate et Jackson.

j'ai déjà considéré que la charge paresseuse est à l'origine du problème, mais j'ai pris des mesures pour dire à Jackson de ne pas traiter les diverses propriétés comme suit:

@JsonIgnoreProperties({ "sentMessages", "receivedMessages", "educationFacility" })
public class Director extends UserAccount implements EducationFacilityUser {
   ....
}

j'ai fait la même chose pour toutes les autres sous-classes UserAccount.

Voici l'exception lancée:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.ArrayList[46]->jobprep.domain.educationfacility.Director_$$_javassist_2["handler"])
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serialize(StdSerializerProvider.java:62)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:268)
    at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:146)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:118)
    at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:236)
    at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:189)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:111)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:296)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:224)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:925)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)

Suggestions sur la façon dont je peux obtenir plus d'information pour voir ce qui cause cela? Quelqu'un sait comment résoudre ce problème?

EDIT: j'ai découvert que getHander() et d'autres méthodes get*() existent sur l'objet proxy. GRR!! Est-ce que je peux dire à Jackson de ne rien traiter sur la procuration, ou suis-je sol? C'est vraiment bizarre parce que la méthode qui crache le JSON ne craque que dans certaines circonstances, pas tout le temps. Néanmoins, c'est dû aux méthodes get*() sur l'objet proxy.

mis à part: les procurations sont mauvaises. Ils perturbent Jackson, equals () et beaucoup d'autres parties de la programmation Java régulière. Je suis tenté de le fossé Hibernate :/

59
demandé sur egervari 2010-12-06 02:57:09

15 réponses

ce n'est pas idéal, mais vous pouvez désactiver L'auto-découverte de Jackson des propriétés JSON, en utilisant @JsonAutoDetect au niveau de la classe. Cela l'empêcherait d'essayer de manier les trucs Javassistes (et d'échouer).

cela signifie que vous devez alors annoter chaque getter manuellement (avec @JsonProperty ), mais ce n'est pas nécessairement une mauvaise chose, car cela garde les choses explicites.

38
répondu skaffman 2010-12-06 00:21:57

j'ai eu un problème similaire avec le chargement paresseux via l'objet proxy hibernate. Je l'ai contourné en annotant la classe ayant chargé des propriétés privées avec:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

je suppose que vous pouvez ajouter les propriétés sur votre objet proxy qui cassent la sérialisation JSON à cette annotation.

"151960920 d'Éviter" de Jackson sur la sérialisation non récupérés paresseux objets

68
répondu Claes Mogren 2017-05-23 10:31:31

j'ai eu la même erreur, mais sans rapport avec L'hibernation. J'ai eu peur de toutes les suggestions effrayantes, ce qui est pertinent en cas d'hibernation et de chargement paresseux... Cependant, dans mon cas j'ai obtenu l'erreur puisque dans une classe intérieure Je n'avais pas getters/setters, de sorte que le BeanSerializer ne pouvait pas sérialiser les données...

L'ajout de getters & setters a résolu le problème.

23
répondu OhadR 2011-11-21 14:26:17

pour ce que ça vaut, il y a Jackson Hibernate module projet qui vient de commencer, et qui devrait résoudre ce problème et, espérons-le, d'autres aussi. Le projet est lié au projet Jackson, mais ne fait pas partie de la source principale. Ceci est principalement pour permettre un processus de publication plus simple; il faudra Jackson 1.7 car C'est à ce moment que L'API de Module est introduite.

9
répondu StaxMan 2010-12-07 17:06:16

j'ai eu le même problème. Voyez si vous utilisez hibernatesession.load() . Si c'est le cas, essayez de convertir en hibernatesession.get() . Cela a résolu mon problème.

6
répondu Jaishankararam 2012-10-26 11:58:32

j'ai eu le même message d'erreur du @RestController de spring . Ma classe de contrôleur rest utilisait la classe JpaRepository de spring et en remplaçant l'appel de méthode repository.getOne(id) par le problème repository.findOne(id) avait disparu.

5
répondu Remis B 2014-04-25 06:27:10

vous pouvez utiliser jackson-datatype-hibernate module pour résoudre ce problème. Il fonctionne pour moi. référence: https://github.com/FasterXML/jackson-datatype-hibernate

4
répondu Howard 2014-02-10 02:26:39

j'ai eu le même problème, les salutations sont ici

"151930920 d'Éviter" de Jackson sur la sérialisation non récupérés paresseux objets

http://blog.pastelstudios.com/2012/03/12/spring-3-1-hibernate-4-jackson-module-hibernate /

https://github.com/nessonqk/jackson-datatype-hibernate

3
répondu Neeson.Z 2017-05-23 12:03:08

comme pour les autres réponses, le problème pour moi était de déclarer une colonne de plusieurs à un pour faire de la recherche paresseuse. Le fait de passer à la récupération rapide a réglé le problème. Avant:

@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.LAZY)

après:

@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.EAGER)
3
répondu riqitang 2016-10-17 15:24:00

, Vous pourriez utiliser @JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" }) annotation sur votre classe "Directeur"

2
répondu atovstonog 2012-07-20 08:50:06

vous pouvez ajouter un Jackson mixin sur L'objet.classe pour toujours ignorer les propriétés liées à l'hibernation. Si vous utilisez Spring Boot mettez ceci dans votre classe D'Application:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
    b.mixIn(Object.class, IgnoreHibernatePropertiesInJackson.class);
    return b;
}


@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private abstract class IgnoreHibernatePropertiesInJackson{ }
1
répondu alarive 2017-05-24 07:15:59

Je suis nouveau à Jackson API, quand j'ai eu l'org.codehaus.Jackson.cartographie.JsonMappingException: Aucun processus trouvé pour la classe com.entreprise.projet.votre classe", j'ai ajouté le getter et le setter à com.entreprise.projet.yourclass, qui m'a aidé à utiliser L'objet Mapper D'ObjectMapper pour écrire l'objet java dans un fichier plat.

0
répondu Anver Sadhat 2012-06-08 09:52:57

j'ai fait face à la même question et il est vraiment étrange que le même code fonctionne dans peu de cas alors qu'il a échoué dans certains cas aléatoires.

Je l'ai fait réparer en m'assurant que le bon setter / getter (S'assurer de la sensibilité du cas)

0
répondu Badal 2013-11-06 07:14:34

j'ai essayé @JsonDetect et

@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })

aucun D'eux ne travaillait pour moi. Utiliser un module tiers m'a semblé être beaucoup de travail. Donc j'ai juste essayé de faire un appel get sur n'importe quelle propriété de l'objet paresseux avant de passer à jackson pour la serlization. Le morceau de code de travail ressemblait à quelque chose comme ceci:

@RequestMapping(value = "/authenticate", produces = "application/json; charset=utf-8")
    @ResponseBody
    @Transactional
    public Account authenticate(Principal principal) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) principal;
        LoggedInUserDetails loggedInUserDetails = (LoggedInUserDetails) usernamePasswordAuthenticationToken.getPrincipal();
        User user = userRepository.findOne(loggedInUserDetails.getUserId());
        Account account = user.getAccount();
        account.getFullName();      //Since, account is lazy giving it directly to jackson for serlization didn't worked & hence, this quick-fix.
        return account;
    }
0
répondu coding_idiot 2015-03-12 20:36:02

vous pouvez également rendre votre directeur d'objet de domaine final. Ce n'est pas une solution parfaite mais cela empêche la création de proxy-sous-classe de votre classe de domaine.

0
répondu DzianisH 2016-09-15 21:16:31