Избегайте сериализации jacksonа на непривлекательных ленивых объектах

У меня есть простой controller, который возвращает объект User, этот пользователь имеет координаты атрибутов, которые имеют свойство hibernate FetchType.LAZY.

Когда я пытаюсь получить этого пользователя, мне всегда приходится загружать все координаты, чтобы получить объект пользователя, иначе, когда jackson попытается выполнить сериализацию, пользователь выдает исключение:

com.fasterxml.jackson.databind.JsonMappingException: невозможно инициализировать прокси – нет сеанса

Это происходит из-за того, что jackson пытается получить этот необработанный объект. Вот объекты:

public class User{ @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") @JsonManagedReference("user-coordinate") private List coordinates; } public class Coordinate { @ManyToOne @JoinColumn(name = "user_id", nullable = false) @JsonBackReference("user-coordinate") private User user; } 

И controller:

 @RequestMapping(value = "/user/{username}", method=RequestMethod.GET) public @ResponseBody User getUser(@PathVariable String username) { User user = userService.getUser(username); return user; } 

Есть ли способ сказать jacksonу не сериализовывать выделенные объекты? Я искал другие ответы, опубликованные 3 года назад, внедрение модуля jackson-hibernate. Но, вероятно, это может быть достигнуто с помощью новой функции jackson.

Мои версии:

  • Весна 3.2.5
  • Спящий режим 4.1.7
  • jackson 2.2

Заранее спасибо.

10 Solutions collect form web for “Избегайте сериализации jacksonа на непривлекательных ленивых объектах”

Я наконец нашел решение! благодаря indybee за то, что дал мне ключ.

Учебник Spring 3.1, Hibernate 4 и Jackson-Module-Hibernate имеют хорошее решение для Spring 3.1 и более ранних версий. Но поскольку версия 3.1.2 Spring имеет свой собственный MappingJackson2HttpMessageConverter с почти теми же функциями, что и в учебнике, поэтому нам не нужно создавать этот настраиваемый HTTPMessageConverter.

С javaconfig нам также не нужно создавать HibernateAwareObjectMapper , нам просто нужно добавить Hibernate4Module к MappingJackson2HttpMessageConverter по умолчанию, который уже имеется Spring, и добавить его в HttpMessageConverters приложения, поэтому нам необходимо:

  1. Расширьте наш весенний конфигурационный class из WebMvcConfigurerAdapter и переопределите метод configureMessageConverters .

  2. По этому методу добавьте MappingJackson2HttpMessageConverter с Hibernate4Module, зарегистрированным в методе previus.

Наш class конфигурации должен выглядеть так:

 @Configuration @EnableWebMvc public class MyConfigClass extends WebMvcConfigurerAdapter{ //More configuration.... /* Here we register the Hibernate4Module into an ObjectMapper, then set this custom-configured ObjectMapper * to the MessageConverter and return it to be added to the HttpMessageConverters of our application*/ public MappingJackson2HttpMessageConverter jacksonMessageConverter(){ MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); ObjectMapper mapper = new ObjectMapper(); //Registering Hibernate4Module to support lazy objects mapper.registerModule(new Hibernate4Module()); messageConverter.setObjectMapper(mapper); return messageConverter; } @Override public void configureMessageConverters(List> converters) { //Here we add our custom-configured HttpMessageConverter converters.add(jacksonMessageConverter()); super.configureMessageConverters(converters); } //More configuration.... } 

Если у вас есть xml-конфигурация, вам не нужно создавать свой собственный MappingJackson2HttpMessageConverter, но вам нужно создать персонализированный картограф, который появляется в учебнике (HibernateAwareObjectMapper), поэтому ваша xml-конфигурация должна выглядеть так:

        

Надеюсь, что этот ответ будет понятным и поможет кому-то найти решение этой проблемы, любые вопросы не стесняйтесь спрашивать!

Начиная с Spring 4.2 и используя Spring Boot и javaconfig, регистрация Hibernate4Module теперь так же просто, как добавить это в вашу конфигурацию:

 @Bean public Module datatypeHibernateModule() { return new Hibernate4Module(); } 

ref: https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

Это похоже на принятое решение @rick.

Если вы не хотите касаться существующей конфигурации конвертеров сообщений, вы можете просто объявить компонент Jackson2ObjectMapperBuilder следующим образом:

 @Bean public Jackson2ObjectMapperBuilder configureObjectMapper() { return new Jackson2ObjectMapperBuilder() .modulesToInstall(Hibernate4Module.class); } 

Не забудьте добавить следующую зависимость к вашему файлу Gradle (или Maven):

 compile 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate4:2.4.4' 

Полезно, если у вас есть приложение для загрузки весны, и вы хотите сохранить возможность изменять функции jacksonа из файла application.properties .

В случае Spring Data Rest тогда, когда решение, отправленное @ r1ckr, работает, все, что требуется, – это добавить одну из следующих зависимостей в зависимости от версии Hibernate:

  com.fasterxml.jackson.datatype jackson-datatype-hibernate4 ${jackson.version}  

или

  com.fasterxml.jackson.datatype jackson-datatype-hibernate5 ${jackson.version}  

В Spring Data Rest существует class:

org.springframework.data.rest.webmvc.json.Jackson2DatatypeHelper

который автоматически определит и зарегистрирует модуль при запуске приложения.

Однако существует проблема:

Проблема Сериализация Lazy @ManyToOne

Если вы используете XML-конфигурацию и используете , я обнаружил, что вам нужно вложить внутри как рекомендовано в учетной записи Jackson Github .

Вот так:

          

`

Для тех, кто пришел сюда, чтобы найти решение для службы RESTful на базе Apache CXF, конфигурация, которая его исправляет, приведена ниже:

       

Где HibernateAwareObjectMapper определяется как:

 public class HibernateAwareObjectMapper extends ObjectMapper { public HibernateAwareObjectMapper() { registerModule(new Hibernate5Module()); } } 

Следующая зависимость требуется по состоянию на июнь 2016 года (при условии, что вы используете Hibernate5):

  com.fasterxml.jackson.datatype jackson-datatype-hibernate5 2.7.4  

Вы можете использовать следующий помощник из проекта Spring Data Rest:

 Jackson2DatatypeHelper.configureObjectMapper(objectMapper); 

Я попробовал полезный ответ @ rick , но столкнулся с проблемой, что «хорошо известные модули», такие как jackson-datatype-jsr310, не были автоматически зарегистрированы, несмотря на то, что они находятся на пути к classам. (Это сообщение в блоге объясняет автоматическую регистрацию.)

Развернувшись на ответе @ rick, вот вам вариант Jackson2ObjectMapperBuilder Spring для создания ObjectMapper . Это автоматически регистрирует «известные модули» и устанавливает некоторые функции в дополнение к установке Hibernate4Module .

 @Configuration @EnableWebMvc public class MyWebConfig extends WebMvcConfigurerAdapter { // get a configured Hibernate4Module // here as an example with a disabled USE_TRANSIENT_ANNOTATION feature private Hibernate4Module hibernate4Module() { return new Hibernate4Module().disable(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION); } // create the ObjectMapper with Spring's Jackson2ObjectMapperBuilder // and passing the hibernate4Module to modulesToInstall() private MappingJackson2HttpMessageConverter jacksonMessageConverter(){ Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .modulesToInstall(hibernate4Module()); return new MappingJackson2HttpMessageConverter(builder.build()); } @Override public void configureMessageConverters(List> converters) { converters.add(jacksonMessageConverter()); super.configureMessageConverters(converters); } } 

Хотя этот вопрос немного отличается от этого: исключение Strange Jackson при сериализации объекта Hibernate , основная проблема может быть исправлена ​​таким же образом с помощью этого кода:

 @Provider public class MyJacksonJsonProvider extends JacksonJsonProvider { public MyJacksonJsonProvider() { ObjectMapper mapper = new ObjectMapper(); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); setMapper(mapper); } } 

Я попробовал это и работал:

// настраиваемая конфигурация для ленивой загрузки

 public static class HibernateLazyInitializerSerializer extends JsonSerializer { @Override public void serialize(JavassistLazyInitializer initializer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { jsonGenerator.writeNull(); } } 

и сконфигурировать mapper:

  mapper = new JacksonMapper(); SimpleModule simpleModule = new SimpleModule( "SimpleModule", new Version(1,0,0,null) ); simpleModule.addSerializer( JavassistLazyInitializer.class, new HibernateLazyInitializerSerializer() ); mapper.registerModule(simpleModule); 
  • Spring: namespace vs contextConfigИнтересные параметры размещения в web.xml
  • Spring MVC + JSON = 406 Не допускается
  • Как добавить зависимость от Spring Boot Jar в другом проекте?
  • Как настроить MappingJacksonHttpMessageConverter, используя конфигурацию с пружинной аннотацией?
  • Список как объект поддержки формы с использованием весны 3 mvc, правильный синтаксис?
  • Инициализация Log4J с помощью Spring?
  • Spring Java Config vs Jboss 7
  • Spring + Hibernate: другой объект с тем же значением идентификатора уже был связан с сеансом
  • как читать переменную системной среды в Spring applicationContext
  • Автоматическая проводка списка с использованием схемы util дает NoSuchBeanDefinitionException
  • Как вернуть пользовательский объект из запроса Spring JPA GROUP BY
  • Interesting Posts

    Какой размер источника питания мне понадобится для компьютера с этими спецификациями?

    Профайлинг Windows XP?

    Центр обновления Windows: «Некоторые настройки управляются вашим системным администратором»

    В чем разница между C # Reference и указателем?

    Какие рекомендации для дизайна электронной почты HTML существуют?

    Скопируйте файл в эффективном, безопасном и эффективном виде

    выполнение действия очистки непосредственно перед выходом node.js

    В чем различия между «родовыми» типами в C ++ и Java?

    Как удалить всплывающие окна adtyty.google.com с ** ПК **? (Перенаправление Tradeadexchange.)

    Должны ли ноутбуки оставаться включенными, когда их батарея заряжается на 100%?

    Как определить, является ли диск жестким диском или SSD в Windows 8?

    ошибка keytool Keystore была изменена или пароль был неверен

    Как просмотреть иерархическую структуру пакета в проводнике пакетов Eclipse

    Назначение охранников

    Как я могу отключить GPS программно в android?

    Давайте будем гением компьютера.