Message converters: HttpMessageConverter, registering cus… — Cracked Java
// Spring Framework & Spring Boot · Spring MVC & REST
SeniorTheoryCoding

Message converters: HttpMessageConverter, registering custom ones.

An HttpMessageConverter is the component that turns Java objects into HTTP bodies and back — it's the engine behind @RequestBody and @ResponseBody. Every time Spring deserializes a JSON payload into a DTO or serializes your return value into the response, a converter did the work.

The contract

The interface has two directions, each gated by a media-type check:

public interface HttpMessageConverter<T> {
    boolean canRead(Class<?> clazz, MediaType mediaType);   // body -> object
    boolean canWrite(Class<?> clazz, MediaType mediaType);  // object -> body
    List<MediaType> getSupportedMediaTypes();
    T read(Class<? extends T> clazz, HttpInputMessage in);
    void write(T t, MediaType contentType, HttpOutputMessage out);
}

RequestResponseBodyMethodProcessor (the argument resolver / return-value handler for @RequestBody/@ResponseBody) iterates the registered converters and uses the first whose canRead/canWrite matches the target type and the negotiated media type.

The defaults Boot registers

With spring-boot-starter-web you get, among others: MappingJackson2HttpMessageConverter (JSON), StringHttpMessageConverter, ByteArrayHttpMessageConverter, ResourceHttpMessageConverter, form converters, and — if jackson-dataformat-xml is present — MappingJackson2XmlHttpMessageConverter. This is why JSON "just works" and why adding the XML module is all it takes to support XML.

Registering a custom converter

Use WebMvcConfigurer. Prefer extendMessageConverters (keeps defaults) over configureMessageConverters (replaces them):

@Configuration
class ConverterConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(0, new ProtobufHttpMessageConverter()); // index 0 = highest priority
    }
}

Ordering matters: converters are tried in list order, so inserting at index 0 gives yours priority for the media types it claims.

Customizing, not replacing

Often you don't need a new converter — you need to tune Jackson. Define an ObjectMapper bean or a Jackson2ObjectMapperBuilderCustomizer, and Boot wires it into the existing JSON converter (e.g. snake_case, ignore-unknown, custom date format). That's lighter than writing a converter from scratch.

Mark your status