it-swarm.com.ru

При сериализации объекта Hibernate выдается странное исключение Джексона

Джексон выбрасывает странное исключение, которое я не знаю, как исправить. Я использую Spring, Hibernate и Jackson.

Я уже считал, что проблема связана с отложенной загрузкой, но я принял меры, чтобы Джексон НЕ обрабатывал различные свойства следующим образом:

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

Я сделал то же самое для всех других подклассов UserAccount.

Вот исключение:

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)

Предложения о том, как я могу получить больше информации, чтобы увидеть, что вызывает это? Кто-нибудь знает, как это исправить?

Правка: Я обнаружил, что getHander () и другие методы get * () существуют на прокси-объекте. GRR !! Можно ли как-то сказать, чтобы Джексон ничего не обрабатывал на прокси, или я сол? Это действительно странно, потому что метод, который выплевывает JSON, падает только при определенных обстоятельствах, а не постоянно. Тем не менее, это связано с методами get * () в прокси-объекте.

В стороне: Прокси - это зло. Они нарушают Джексона, equals () и многие другие части обычного Java-программирования. Я испытываю желание полностью отказаться от Hibernate: /

60
egervari

Это не идеально, но вы можете отключить автоматическое обнаружение свойств JSON Джексоном, используя @JsonAutoDetect на уровне класса. Это помешало бы ему попытаться справиться с вещами Javassist (и потерпеть неудачу).

Это означает, что вам нужно будет вручную аннотировать каждый получатель (с помощью @JsonProperty), но это не обязательно плохо, так как это делает вещи явными.

38
skaffman

У меня была похожая проблема с отложенной загрузкой через прокси-объект hibernate. Обошел его, аннотируя класс с lazyloaded частными свойствами с помощью:

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

Я предполагаю, что вы можете добавить свойства к вашему прокси-объекту, который нарушает сериализацию JSON к этой аннотации.

Избегайте сериализации Джексона на невнятых ленивых объектах

68
Claes Mogren

я получил ту же ошибку, но без отношения к Hibernate. Я испугался здесь всех пугающих предложений, которые, я думаю, уместны в случае Hibernate и отложенной загрузки ... Однако в моем случае я получил ошибку, поскольку во внутреннем классе у меня не было методов получения/установки, поэтому BeanSerializer не удалось сериализовать данные ... 

Добавление геттеров и сеттеров решило проблему.

23
OhadR

Что бы это ни стоило, есть модуль Jackson Hibernate проект, который только начался, и который должен решить эту проблему и, надеюсь, и другие ........ Проект связан с проектом Джексона, хотя и не является частью основного источника. Это в основном для упрощения процесса выпуска; для этого потребуется Jackson 1.7, так как именно тогда вводится Module API.

9
StaxMan

У меня такая же проблема. Посмотрите, используете ли вы hibernatesession.load(). Если это так, попробуйте преобразовать в hibernatesession.get(). Это решило мою проблему.

6
Jaishankararam

У меня было то же сообщение об ошибке от @RestController Spring. Мой класс контроллера rest использовал класс Spring JpaRepository и, заменив вызов метода repository.getOne(id) на repository.findOne(id), проблема исчезла. 

5
Remis B

Вы можете использовать модуль jackson-datatype-hibernate для решения этой проблемы. Это работает для меня . Ссылка: https://github.com/FasterXML/jackson-datatype-hibernate

4
Howard
3
Neeson.Z

Как и в других ответах, проблема для меня заключалась в том, чтобы объявить столбец «многие к одному» для выполнения отложенной выборки. Переход к активному извлечению исправил проблему . До:

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

После:

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

Вы можете добавить миксин Джексона в Object.class, чтобы всегда игнорировать свойства, связанные с гибернацией. Если вы используете Spring Boot, поместите это в свой класс 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

Вы можете использовать аннотацию @JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" }) в своем классе «Директор»

2
atovstonog

Я пробовал @JsonDetect и

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

Ни один из них не работал для меня. Использование стороннего модуля показалось мне большой работой. Поэтому я просто попытался сделать вызов get для любого свойства ленивого объекта, прежде чем перейти к jackson для серлизации. Фрагмент рабочего кода выглядел примерно так:

@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

Я новичок в Jackson API, когда я получил «org.codehaus.jackson.map.JsonMappingException: не найден сериализатор для класса com.company.project.yourclass», я добавил геттер и сеттер в com.company.project.yourclass , это помогло мне использовать объект mapper ObjectMapper для записи объекта Java в плоский файл.

0
Anver Sadhat

Я столкнулся с той же проблемой, и это действительно странно, что один и тот же код работает в нескольких случаях, тогда как в некоторых случайных случаях он не работал. 

Я исправил это, просто убедившись в правильности установки/получения (убедившись, что регистр чувствителен)

0
Badal

Также вы можете сделать свой домен директором объекта final. Это не идеальное решение, но оно не позволяет создавать прокси-подкласс вашего класса домена.

0
DzianisH