Quick Table of Contents
- Create a custom mapper class
- Create a custom ObjectMapper
- Register classes in the Spring context
- Links
How to customise the Jackson JSON mapper in Spring Web MVC
Spring MVC using annotations is great for AJAX + JSON until you need to customise the JSON mapping.
If you are using Spring 3.1 take a look at configuring a message converter as part of mvc namespace config for an more elegant solution.
There is an option to add annotations directly to your model classes, but if you want to keep them separate you can do the following:
1. Create a custom mapper class
In this example we are using joda-time's LocalDate, and want to serialize this to as a "yyyy-MM-dd" formatted String, instead of the provided 3 field mapping.
public class LocalDateSerializer extends SerializerBase<LocalDate> {
public LocalDateSerializer() {
super(LocalDate.class);
}
@Override
public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.toString()); // this returns the date as "yyyy-MM-dd"
}
@Override
public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
throw new UnsupportedOperationException();
}
}
2. Create a custom ObjectMapper
Create a custom ObjectMapper by extending the default Jackson ObjectMapper.
@Component
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
CustomSerializerFactory sf = new CustomSerializerFactory();
sf.addSpecificMapping(LocalDate.class, new LocalDateSerializer());
this.setSerializerFactory(sf);
}
}3. Register classes in the Spring context
Register the new mapper at start up, by getting at the beans that were created by "<mvc:annotation-driven />"
@Component
public class JacksonFix {
private AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter;
private CustomObjectMapper objectMapper;
@PostConstruct
public void init() {
HttpMessageConverter<?>[] messageConverters = annotationMethodHandlerAdapter.getMessageConverters();
for (HttpMessageConverter<?> messageConverter : messageConverters) {
if (messageConverter instanceof MappingJacksonHttpMessageConverter) {
MappingJacksonHttpMessageConverter m = (MappingJacksonHttpMessageConverter) messageConverter;
m.setObjectMapper(objectMapper);
}
}
}
// this will exist due to the <mvc:annotation-driven/> bean
@Autowired
public void setAnnotationMethodHandlerAdapter(AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter) {
this.annotationMethodHandlerAdapter = annotationMethodHandlerAdapter;
}
@Autowired
public void setObjectMapper(CustomObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
}If you are using IntelliJ, you can add a suppress warning annotation at the top of the file:
@SuppressWarnings({"SpringJavaAutowiringInspection"})
Spring will set the 2 fields first, then run the init() method. It will 'dig' at the existing beans and find the Jackson converter, then replace the default object mapper with the custom object mapper.

