Как внедрить зависимость в сериализатор Jackson Custom - PullRequest
1 голос
/ 15 февраля 2020

В этом вопросе я видел интересный подход для внедрения объектов в пользовательские десериализаторы для каркаса отображения Джексона (в настоящее время я использую версию 2.10.x ). По сути, регистрируется зависимость MyService в ObjectMapper

 jsonMapper.setInjectableValues(new InjectableValues
                .Std()
                .addValue(MyService.class.getName(), myServiceInstance));

, а затем в классе, который расширяет StdDeserializer, к нему можно получить доступ через DeserializationContext, который имеет метод findInjectableValue.

Теперь, я надеюсь, библиотека предоставляет симметричный c подход для сериализации, но, честно говоря, не смог найти его. В частности, если у вас есть класс, который расширяет StdSerializer, вам нужно будет реализовать метод serialize(ProjectSerializable value, JsonGenerator jsonGenerator, SerializerProvider provider), который, кажется, не имеет класса с аналогичными функциями DeserializationContext.

Итак, как можно можно добиться такого же «впрыскивания» с помощью настраиваемого сериализатора, не прибегая к уродливым решениям, основанным на статичном c доступе к поставщикам экземпляров или другим непроверяемым вещам.

1 Ответ

0 голосов
/ 16 февраля 2020

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

Когда вы создаете ObjectMapper, вам необходимо взломать его, создав новый

ObjectMapper objectMapper = ...// here you create the ObjectMapper will all your configs

// Then you inject the service.

SerializationConfig initialSerializationConfig = objectMapper.getSerializationConfig();
ContextAttributes attributes = initialSerializationConfig.getAttributes();
// Here we create a new ContextAttributes with the class we want 
//   to have shared for each serializer
ContextAttributes attributesWithInjectedValue =
         attributes.withSharedAttribute(MyService.class.getName(), myServiceInstance);
SerializationConfig serializationConfigWithInjectedValue =
         initialSerializationConfig.with(attributesWithInjectedValue);

return jsonMapper.setConfig(serializationConfigWithInjectedValue);

Затем в случае JsonSerializer вы просто делаете:

MyService myService = (MyService) serializerProvider
        .getAttribute(MyService.class.getName());

, где serializerProvider - это экземпляр SerializerProvider с помощью метода serialize.

Мне не нравится асимметрия с другим подходом, показанным для десериализации, но он работает.

...