Hi guys,
I'm currently developing a feature in which I rely on Spring's HttpMessageConverter infrastructure and facing a necessity to have control over the configuration of PrettyPrinter instance used in MappingJackson2HttpMessageConverter. E.g. have different indentation. The PrettyPrinter reference is currently private to converter instance and has no accessors available to sub-classes: https://github.com/spring-projects/spring-framework/blob/4a9c7e631c60a12f3426d42143e9e27be0bf68ab/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java#L110 Every other aspect of behavior of MappingJackson2HttpMessageConverter is totally OK to me.
I thought what if you'll start to configure ObjectWriter instance with default pretty printer from Jackson's ObjectMapper settings? I.e. here https://github.com/spring-projects/spring-framework/blob/4a9c7e631c60a12f3426d42143e9e27be0bf68ab/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java#L452 instead of tying it to your very own pretty printer do:
objectWriter = objectWriter.withDefaultPrettyPrinter();
and make ssePrettyPrinter to be the default one in org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#init(ObjectMapper), which is protected and therefore allowed to override. Thus you'll preserving current behavior simultaneously with allowing customization of pretty printer by external consumers.
Or propose your own variant for achieving the same!
We're stuck here at Spring Framework 4.3.25 so I'll have to solve my problem in some other way and won't directly benefit from the resolution of this issue. Still, I think the idea is quite interesting, don't you think so?
Thanks, Dzmitry
Comment From: sbrannen
Hi @dzmitry-chuchva,
Thanks for opening your first issue for the Spring Framework.
At a glance, I think that sounds reasonable, and we'll discuss it within the team.
Comment From: dzmitry-chuchva
Hi @sbrannen,
That's right, it my first one. And just 40 minutes after creation of it I think now it may be not an issue :(
I've just tested MappingJackson2HttpMessageConverter
constructed with ObjectMapper
instance which I've prepared with custom default pretty printer:
class MyMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public MyMappingJackson2HttpMessageConverter() {
super(Jackson2ObjectMapperBuilder.json()
.build()
.setDefaultPrettyPrinter(new DefaultPrettyPrinter()
.withObjectIndenter(new DefaultIndenter(" ", "\n"))));
setPrettyPrint(true);
}
}
and looks like my custom pretty printer gets applied! I do not understand the exact mechanism of this though. I was sure it would get overridden by internal private PrettyPrinter
instance of MappingJackson2HttpMessageConverter
.
I'm ready to close this issue if you do not mind.
Comment From: sbrannen
If selectObjectMapper(...)
returns this.defaultObjectMapper
, then your PrettyPrinter
will be used; whereas, the internal private ssePrettyPrinter
will be used with any ObjectMapper
if contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM)
is true
.
The latter applies to your custom configured ObjectMapper
as well. If you are writing MediaType.TEXT_EVENT_STREAM
, your custom configured PrettyPrinter
will be overridden by the ssePrettyPrinter
.
In summary, I think your solution is fine for the default object mapper, but I think it is a bit odd that Spring will override a custom configured PrettyPrinter
for SSE. So perhaps we should rethink the logic for that.
Comment From: rstoyanchev
Not only if the content-type is SSE but also when indentation is enabled. For those cases we have to ensure correct SSE formatting by prefixing each new line like this:
data: {\n
data: "userId" : "myuser",\n
data: "objectId" : "s1"\n
data: }\n\n
In other words, this is by design.