I was migrating recently to the new Spring Boot version 2. And most annoying thing was that PageImpl (component used for pagination) changed format. Also I had some issues with Mockito 2, but all of them could be solved read here.
Well I found this article and it all looked easy despite the fact that Spring did not want to use my JsonSerializer. Here how it looks:
Next I read Spring docs of how can I customize Serializer here and here
They suggested to create jacksonBuilder with your specific module or register JsonComponentModule that will find your serializer that will be used by spring during mapper creation. Unfortunately none of this worked for me:
And this also didn't work:
I continued with my last idea, suggested by docs is configuring HttpMessageConverter.
And here I figured out that my config extends WebMvcConfigurationSupport to enable MVC and
after debugging spring context creation. I found that Spring registers default converters with method
addDefaultHttpMessageConverters and following line of code and for some reason it does not register serializer here:
Well I found this article and it all looked easy despite the fact that Spring did not want to use my JsonSerializer. Here how it looks:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.springframework.boot.jackson.JsonComponent; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Sort; import java.io.IOException; @JsonComponent public class PageImplJacksonSerializer extends JsonSerializer { @Override public void serialize(PageImpl page, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); jsonGenerator.writeObjectField("content", page.getContent()); jsonGenerator.writeBooleanField("first", page.isFirst()); jsonGenerator.writeBooleanField("last", page.isLast()); jsonGenerator.writeNumberField("totalPages", page.getTotalPages()); jsonGenerator.writeNumberField("totalElements", page.getTotalElements()); jsonGenerator.writeNumberField("numberOfElements", page.getNumberOfElements()); jsonGenerator.writeNumberField("size", page.getSize()); jsonGenerator.writeNumberField("number", page.getNumber()); Sort sort = page.getSort(); jsonGenerator.writeArrayFieldStart("sort"); for (Sort.Order order : sort) { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("property", order.getProperty()); jsonGenerator.writeStringField("direction", order.getDirection().name()); jsonGenerator.writeBooleanField("ignoreCase", order.isIgnoreCase()); jsonGenerator.writeStringField("nullHandling", order.getNullHandling().name()); jsonGenerator.writeEndObject(); } jsonGenerator.writeEndArray(); jsonGenerator.writeEndObject(); } }
@Bean public Module jsonComponentModule() { return new JsonComponentModule(); }
And this also didn't work:
@Bean @Primary public Jackson2ObjectMapperBuilder jacksonBuilder() { JsonComponentModule module = new JsonComponentModule(); module.addSerializer(PageImpl.class, new PageImplJacksonSerializer()); Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.modulesToInstall(module); return builder; }
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
So here is working solution for me, with configuring default converter created by Spring:
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { MappingJackson2HttpMessageConverter converter = (MappingJackson2HttpMessageConverter) converters.stream() .filter(c -> c instanceof MappingJackson2HttpMessageConverter) .findFirst().get(); Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json(); JsonComponentModule module = new JsonComponentModule(); module.addSerializer(PageImpl.class, new PageImplJacksonSerializer()); ObjectMapper objectMapper = builder.modules(module).build(); converter.setObjectMapper(objectMapper); }
Hi,
ReplyDeleteActually there is a simple way that configure PageImplJacksonSerializer's path for component scanning. JsonComponentModule(org.springframework.boot.jackson) registers json beans which annotated with @JsonComponent.
@Configuration
@ComponentScan("com.progrnotes.serializer")
public class SerializerConfig {
}
unfortunately it didn't work for me, spring find it but do not use when i return json from controller
DeleteI had this problem, resolved when removed @EnableWebMvc annotation.......
ReplyDeleteAfter removing @EnableWebMvc annotation, HTTP error 415 is coming in my Rest Web Service.
Delete