WebFlux 7.0.0-M9: AbstractJacksonEncoder
considers the FILTER_PROVIDER_HINT
only when going through encodeValue()
:
https://github.com/spring-projects/spring-framework/blob/04492c3516f2c9882adbd55ae3fa6bafe513f8ef/spring-web/src/main/java/org/springframework/http/codec/AbstractJacksonEncoder.java#L224-L227
however when encoding a Flux<T>
to a non-streaming media type, the hint is ignored.
The filter hint should probably be checked here: https://github.com/spring-projects/spring-framework/blob/04492c3516f2c9882adbd55ae3fa6bafe513f8ef/spring-web/src/main/java/org/springframework/http/codec/AbstractJacksonEncoder.java#L322-L334
Context: I was using MappingJacksonValue
extensively to programmatically add Jackson filters to my responses and am replacing it now with using hints, where I noticed that they are not used for Flux<T>
body types.
Side note: Some guidance on how to actually provide hints would be helpful. The only proper, user-facing API I found was the ServerResponse
builder for functional endpoints. But I haven't found anything on how to provide hints for encoding client requests (WebClient
) or responses returned from @RequestMapping
controller methods.
My current solution is to replace the default JacksonJsonEncoder
with a custom one:
class MyCustomEncoder extends JacksonJsonEncoder {
MyCustomEncoder(JsonMapper jsonMapper) {
super(jsonMapper);
}
@Override
public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType,
Map<String, Object> hints) {
return Flux.deferContextual(reactorContext -> {
FilterProvider myFilter = ...; // Create configured FilterProvider from reactorContext
Map<String, Object> hintsToUse = Hints.merge(hints, JacksonCodecSupport.FILTER_PROVIDER_HINT, myFilter);
return super.encode(inputStream, bufferFactory, elementType, mimeType, hintsToUse);
});
}
@Override
public DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType,
Map<String, Object> hints) {
ContextView reactorContext = Context.empty();
if (hints != null) {
// thank you for putting the context in here 🙏
reactorContext = (ContextView) hints.get(ContextView.class.getName(), Context.empty());
}
FilterProvider myFilter = ...; // Create configured FilterProvider from reactorContext
Map<String, Object> hintsToUse = Hints.merge(hints, JacksonCodecSupport.FILTER_PROVIDER_HINT, myFilter);
return super.encodeValue(value, bufferFactory, valueType, mimeType, hintsToUse);
}
}