it-swarm.com.de

Seltsame Jackson-Ausnahme beim Serialisieren des Hibernate-Objekts

Jackson wirft eine seltsame Ausnahme ab, die ich nicht beheben kann. Ich benutze Spring, Hibernate und Jackson.

Ich habe bereits gedacht, dass Lazy-Loading das Problem verursacht, aber ich habe Maßnahmen ergriffen, um Jackson anzuweisen, verschiedene Eigenschaften NICHT wie folgt zu verarbeiten:

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

Dasselbe habe ich auch für alle anderen UserAccount-Unterklassen getan.

Hier ist die Ausnahme, die geworfen wird:

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)

Vorschläge, wie ich weitere Informationen erhalten kann, um herauszufinden, was dies verursacht? Weiß jemand, wie man das repariert?

EDIT: Ich habe entdeckt, dass getHander () und andere get * () - Methoden im Proxy-Objekt vorhanden sind. GRR !! Gibt es eine Möglichkeit, Jackson zu sagen, dass er nichts auf dem Proxy verarbeiten soll, oder bin ich sol? Das ist wirklich seltsam, da die Methode, die den JSON ausspuckt, nur unter bestimmten Umständen abstürzt, nicht immer. Trotzdem liegt es an den get * () - Methoden des Proxy-Objekts.

Nebenbei: Proxies sind böse. Sie stören Jackson, Equals () und viele andere Teile der normalen Java-Programmierung. Ich bin versucht, den Winterschlaf ganz aufzugeben: /

60
egervari

Dies ist nicht ideal, aber Sie können die automatische Erkennung von JSON-Eigenschaften durch Jackson deaktivieren, indem Sie @JsonAutoDetect auf Klassenebene verwenden. Dies würde verhindern, dass es versucht, mit den Javassist-Sachen umzugehen (und scheitert).

Das bedeutet, dass Sie jeden Getter manuell (mit @JsonProperty) kommentieren müssen. Dies ist jedoch nicht unbedingt eine schlechte Sache, da dies explizit erfolgt.

38
skaffman

Ich hatte ein ähnliches Problem mit dem verzögerten Laden über das Hibernate-Proxy-Objekt. Umging es durch Annotieren der Klasse, die private Immobilien lazyloaded hatte:

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

Ich gehe davon aus, dass Sie die Eigenschaften Ihres Proxy-Objekts hinzufügen können, die die JSON-Serialisierung zu dieser Anmerkung unterbrechen.

Vermeiden Sie Jackson-Serialisierung bei nicht abgerufenen Lazy-Objekten

68
Claes Mogren

ich habe den gleichen Fehler, aber ohne Beziehung zu Hibernate. Ich hatte hier Angst vor allen beängstigenden Vorschlägen, die ich für Hibernate und Lazy Loading als relevant erachte, aber in meinem Fall bekam ich den Fehler, da ich in einer inneren Klasse keine Getter/Setter hatte, so der BeanSerializer konnte die Daten nicht serialisieren ... 

Das Hinzufügen von Gettern und Setters löste das Problem.

23
OhadR

Für das, was es wert ist, gibt es das Jackson Hibernate-Modul Projekt, das gerade erst begonnen hat und das dieses Problem und hoffentlich auch andere lösen soll .. _ Das Projekt ist mit dem Jackson-Projekt verwandt, obwohl es nicht Teil der Kernquelle ist. Dies dient hauptsächlich dazu, einen einfacheren Freigabeprozess zu ermöglichen. Es wird Jackson 1.7 erfordern, da die Modul-API eingeführt wird.

9
StaxMan

Ich hatte das gleiche Problem. Prüfen Sie, ob Sie hibernatesession.load() verwenden. Wenn ja, versuchen Sie, in hibernatesession.get() zu konvertieren. Das hat mein Problem gelöst.

6
Jaishankararam

Ich hatte die gleiche Fehlermeldung aus @RestController des Frühlings. Meine Rest-Controller-Klasse benutzte die JpaRepository-Klasse von Spring und durch das Ersetzen des repository.getOne(id)-Methodenaufrufs durch das repository.findOne(id)-Problem war es vorbei. 

5
Remis B

Sie können das Modul jackson-datatype-hibernate verwenden, um dieses Problem zu lösen. Es funktioniert für mich . Referenz: https://github.com/FasterXML/jackson-datatype-hibernate

4
Howard
3
Neeson.Z

Ähnlich wie bei anderen Antworten bestand das Problem für mich darin, eine vielzählige Kolumne für das faule Abholen zu definieren. Der Umstieg auf eifrigen Abruf behebte das Problem . Vorher:

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

Nach dem:

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

Sie können ein Jackson-Mixin zu Object.class hinzufügen, um die Eigenschaften des Hibernats immer zu ignorieren. Wenn Sie Spring Boot verwenden, fügen Sie dies in Ihre Application-Klasse ein:

@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

Sie können @JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" }) Annotation in Ihrer Klasse "Director" verwenden.

2
atovstonog

Ich habe versucht @JsonDetect Und

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

Keiner von beiden hat für mich gearbeitet. Die Verwendung eines Drittanbieter-Moduls schien mir eine Menge Arbeit zu bedeuten. Deshalb habe ich gerade versucht, eine Eigenschaft des Lazy-Objekts mit get aufzurufen, bevor ich zur Serlisierung an jackson übergeben habe. Das Arbeitscode-Snippet sah ungefähr so ​​aus:

@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
coding_idiot

Ich bin neu bei Jackson API. Als ich die "org.codehaus.jackson.map.JsonMappingException: Kein Serializer für die Klasse com.company.project.yourclass" gefunden habe, habe ich com.company.project.yourclass mit dem Getter und Setter versehen Das hat mir geholfen, das Mapper-Objekt des ObjectMapper zu verwenden, um das Java-Objekt in eine flache Datei zu schreiben.

0
Anver Sadhat

Ich war mit dem gleichen Problem konfrontiert und es ist wirklich merkwürdig, dass derselbe Code in wenigen Fällen funktioniert, während er in einigen zufälligen Fällen fehlgeschlagen ist. 

Ich habe das Problem behoben, indem ich nur den richtigen Setter/Getter vergewisserte (Sicherstellung der Groß-/Kleinschreibung)

0
Badal

Sie können auch Ihr Domänenobjekt Director als final festlegen. Es ist keine perfekte Lösung, verhindert jedoch die Erstellung einer Proxy-Unterklasse Ihrer Domänenklasse.

0
DzianisH