1

In this question I've seen an interesting approach for injecting objects into custom deserializers for the Jackson mapping framework (I'm currently on version 2.10.x). Essentially, one registers a dependency MyService in the ObjectMapper

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

and then in a class that extends StdDeserializer it can be accessed through the DeserializationContext which has a findInjectableValue method.

Now, I hope the library provides a symmetric approach for serialisation, but honestly could not find it. Specifically, if you have a class that extends StdSerializer, you will need to implement a method serialize(ProjectSerializable value, JsonGenerator jsonGenerator, SerializerProvider provider) which doesn't seems to have a class with similar features of DeserializationContext.

So, how can one achieve the same "injection" with a custom serializer without resorting to ugly solutions based on static access to instance providers or other untestable things.

JeanValjean
  • 17,172
  • 23
  • 113
  • 157

1 Answers1

0

It seems to me that the only way to achieve this is via setting attributes for the SerializerProvider that will be used by the custom serializer.

When you create the ObjectMapper, then you have to hack it by creating a new one

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);

Then in the instance of the JsonSerializer you simply do:

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

where serializerProvider is the instance of SerializerProvider given with the serialize method.

I don't like the asymmetry with the other approach shown for deserialization, but it works.

JeanValjean
  • 17,172
  • 23
  • 113
  • 157