web-dev-qa-db-fra.com

Étrange exception Jackson déclenchée lors de la sérialisation d'un objet Hibernate

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

J'ai déjà considéré que le chargement paresseux est à l'origine du problème, mais j'ai pris des mesures pour dire à Jackson de NE PAS traiter diverses propriétés comme suit:

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

J'ai également fait la même chose pour toutes les autres sous-classes de UserAccount.

Voici l'exception levé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$1.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'informations pour voir ce qui en est la cause? Quelqu'un sait comment réparer ça?

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 le proxy, ou suis-je solitaire? C'est vraiment bizarre parce que la méthode qui crache le JSON ne plante que dans certaines circonstances, pas tout le temps. Néanmoins, cela est dû aux méthodes get * () sur l'objet proxy.

A part: les procurations sont diaboliques. Ils perturbent Jackson, equals () et de nombreux autres éléments de la programmation Java régulière. Je suis tenté de laisser tomber Hibernate complètement: /

60
egervari

Ce n'est pas idéal, mais vous pouvez désactiver la détection automatique des propriétés JSON par Jackson, en utilisant @JsonAutoDetect au niveau de la classe. Cela l’empêcherait d’essayer de gérer le truc Javassiste (et d’échouer).

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

38
skaffman

J'ai eu un problème similaire avec le chargement différé via l'objet proxy hibernate. Pour contourner le problème en annotant la classe ayant des propriétés privées lazyloaded avec:

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

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

Évitez la sérialisation de Jackson sur des objets paresseux non récupérés

68
Claes Mogren

j'ai eu la même erreur, mais sans relation avec Hibernate. J'ai eu peur ici de toutes les suggestions effrayantes, ce qui me semble pertinent dans le cas d'Hibernate et de chargement paresseux .... Cependant, dans mon cas, j'ai eu l'erreur car dans une classe intérieure je n'avais pas de getters/setters ne pouvait pas sérialiser les données ... 

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

23
OhadR

Pour ce que ça vaut, il y a module Jackson Hibernate 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 des sources principales. Ceci est principalement pour permettre un processus de publication plus simple; Jackson 1.7 sera nécessaire à l’introduction de l’API de module.

9
StaxMan

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

6
Jaishankararam

J'ai eu le même message d'erreur du @RestController de spring. Ma classe de contrôleur de repos 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), disparaissait. 

5
Remis B

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

4
Howard
3
Neeson.Z

Semblable à d'autres réponses, le problème pour moi était de déclarer une colonne plusieurs-à-un pour effectuer des extractions paresseuses. Le passage à l'extraction rapide a résolu le problème ..___ Avant:

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

Après:

@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.EAGER)
3
riqitang

Vous pouvez ajouter un mixin Jackson sur Object.class pour toujours ignorer les propriétés liées à hibernate. Si vous utilisez Spring Boot, mettez ceci dans votre classe Application:

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


@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private abstract class IgnoreHibernatePropertiesInJackson{ }
2
alarive

Vous pouvez utiliser l'annotation @JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" }) sur votre classe "Director"

2
atovstonog

Je suis nouveau dans l'API Jackson, quand j'ai reçu le "org.codehaus.jackson.map.JsonMappingException: aucun sérialiseur trouvé pour la classe com.company.project.yourclass", j'ai ajouté le getter et le configurateur à com.company.project.yourclass Cela m’a aidé à utiliser l’objet mappeur d’ObjectMapper pour écrire l’objet Java dans un fichier plat.

0
Anver Sadhat

J'ai été confronté au même problème et il est vraiment étrange que le même code fonctionne dans peu de cas, alors qu'il a échoué dans certains cas. 

Je l'ai fait réparer en s'assurant que le setter/getter approprié (en s'assurant de la sensibilité à la casse)

0
Badal

Vous pouvez également rendre votre objet de domaine Director final. Ce n'est pas une solution parfaite mais cela empêche de créer une sous-classe proxy de votre classe de domaine.

0
DzianisH