Исключение Strange Jackson, возникающее при сериализации объекта 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)
Предложения о том, как я могу получить больше информации, чтобы узнать, что вызывает это? Кто-нибудь знает, как это исправить?
EDIT: Я обнаружил, что getHander() и другие методы get *() существуют на прокси-объекте. GRR!! Есть ли какой-либо способ, которым я могу сказать, что Джексон не обрабатывал ничего на прокси, или я зов? Это действительно странно, потому что метод, который выплевывает JSON, падает только при определенных обстоятельствах, не все время. Тем не менее, это связано с методами get *() на прокси-объекте.
Кроме того, Прокси - зло. Они нарушают Jackson, equals() и многие другие части обычного программирования Java. Я испытываю соблазн полностью отказаться от Hibernate:/
Ответы
Ответ 1
Это не идеально, но вы можете отключить автоматическое обнаружение свойств JSON Джексона, используя @JsonAutoDetect
на уровне класса. Это помешало бы ему попытаться обработать материал Javassist (и потерпеть неудачу).
Это означает, что вам нужно вручную аннотировать каждый получатель (с помощью @JsonProperty
), но это не обязательно плохо, поскольку оно сохраняет явные вещи.
Ответ 2
У меня была аналогичная проблема с ленивой загрузкой через прокси-объект hibernate. Общайтесь с ним, аннотируя класс, имеющий lazyloaded private properties:
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Я предполагаю, что вы можете добавить свойства на свой прокси-объект, который разбивает сериализацию JSON на эту аннотацию.
Избегайте сериализации Джексона на непривлекательных ленивых объектах
Ответ 3
я получил ту же ошибку, но без отношения к Hibernate. Я испугался здесь от всех пугающих предложений, которые, я думаю, уместно в случае Hibernate и ленивой загрузки...
Однако в моем случае я получил ошибку, так как во внутреннем классе у меня не было геттеров/сеттеров, поэтому BeanSerializer не смог сериализовать данные...
Добавление геттеров и сеттеров разрешило проблему.
Ответ 4
Для чего стоит проект Jackson Hibernate module, который только начинался, и который должен решить эту проблему и, надеюсь, и другие.
Проект связан с проектом Джексона, хотя он и не является частью основного источника. Это в основном для упрощения процесса выпуска; это потребует от Jackson 1.7, когда внедряется модуль API.
Ответ 5
У меня была та же проблема. Посмотрите, используете ли вы hibernatesession.load()
. Если да, попробуйте преобразовать в hibernatesession.get()
. Это решило мою проблему.
Ответ 6
У меня было такое же сообщение об ошибке от spring @RestController
. Класс контроллера останова использовал класс spring JpaRepository
, и, заменив вызов repository.getOne(id)
методом repository.findOne(id)
, проблема исчезла.
Ответ 7
Вы можете использовать модуль jackson-datatype-hibernate для решения этой проблемы. Это работает для меня.
ссылка: https://github.com/FasterXML/jackson-datatype-hibernate
Ответ 8
У меня такая же проблема, приветствия здесь
Избегайте сериализации Джексона на непривлекательных ленивых объектах
http://blog.pastelstudios.com/2012/03/12/spring-3-1-hibernate-4-jackson-module-hibernate/
https://github.com/nessonqk/jackson-datatype-hibernate
Ответ 9
Вы можете использовать аннотацию @JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })
для вашего класса "Директор"
Ответ 10
Как и в других ответах, проблема для меня заключалась в том, чтобы объявить столбец "один-к-одному", чтобы сделать ленивый выбор. Исправлена проблема переключения на целевую выборку.
До:
@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.LAZY)
После:
@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.EAGER)
Ответ 11
Я новичок в API Jackson, когда получил "org.codehaus.jackson.map.JsonMappingException: сериализатор не найден для класса com.company.project.yourclass", я добавил геттер и setter в com.company. project.yourclass, который помог мне использовать объект Mapper ObjectMapper для записи объекта java в плоский файл.
Ответ 12
Я столкнулся с той же проблемой, и действительно странно, что один и тот же код работает в нескольких случаях, в то время как в некоторых случайных случаях он не срабатывает.
Я исправил это, просто убедившись, что правильный сеттер/геттер (убедитесь, что чувствительность к регистру)
Ответ 13
Я пробовал @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;
}
Ответ 14
Кроме того, вы можете сделать конечный объект вашего объекта домена. Это не идеальное решение, но оно предотвращает создание прокси-подкласса вашего класса домена.
Ответ 15
Вы можете добавить микшер Jackson в 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{ }