Fixing Spring Boot Preferring XML Over JSON After Upgrade

-

Fixing Spring Boot Preferring XML Over JSON After Upgrade

The Problem

After upgrading to Spring Boot 3.5.3, developers noticed that Spring started preferring XML over JSON when no Content-Type header was explicitly provided.

Inspecting the registered HttpMessageConverters revealed this order:

ByteArrayHttpMessageConverter
StringHttpMessageConverter
ResourceHttpMessageConverter
AllEncompassingFormHttpMessageConverter
MappingJackson2XmlHttpMessageConverter
MappingJackson2HttpMessageConverter

Since XML converter appears before JSON, the framework defaults to XML, leading to surprising results:

  • Default error pages returned as XML
  • @ControllerAdvice responses serialized as XML
  • RestTemplate POSTs defaulting to XML instead of JSON

This behavior wasn’t present in Spring Boot 3.2.x, making the upgrade seem like a breaking change.


🧠 Why It Happens

Spring Boot auto-registers message converters based on what’s found on the classpath.

  • If jackson-dataformat-xml is present, Spring automatically configures MappingJackson2XmlHttpMessageConverter.
  • Converters are then ordered, and XML ends up ahead of JSON in some cases.

In the reported case, the root cause was introducing JasperReports, which brought in:

com.fasterxml.jackson.dataformat:jackson-dataformat-xml

That dependency enabled XML support unintentionally. Without XML on the classpath, JSON is always preferred.


Solutions

1. Remove or Exclude XML Support

If your application doesn’t need XML at all, the cleanest fix is to exclude jackson-dataformat-xml from your dependencies.

Maven example:

<dependency>
  <groupId>net.sf.jasperreports</groupId>
  <artifactId>jasperreports</artifactId>
  <version>...</version>
  <exclusions>
    <exclusion>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-xml</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Gradle example:

implementation("net.sf.jasperreports:jasperreports") {
    exclude group: "com.fasterxml.jackson.dataformat", module: "jackson-dataformat-xml"
}

2. Force JSON as Default on the Server

If XML must remain available but JSON should be the default, configure Spring MVC:

# application.properties
spring.mvc.contentnegotiation.default-content-type=application/json

This ensures that when the client doesn’t send a header, JSON is returned instead of XML.


3. Enforce JSON in RestTemplate

On the client side, if you use RestTemplate, you can override the default converters:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
            .messageConverters(new MappingJackson2HttpMessageConverter())
            .build();
}

Alternatively, add a ClientHttpRequestInterceptor that injects Content-Type: application/json into outgoing requests.


Final Root Cause

In the real case, the developer confirmed:

“Seems you found the issue, we introduced JasperReports, which brought in jackson-dataformat-xml, and Spring started using it.”
https://stackoverflow.com/questions/79762083/spring-changed-converters-order-prefering-xml

So the unexpected behavior wasn’t a Spring Boot bug, but a dependency side-effect.


Conclusion

If you suddenly see XML responses in a Spring Boot app after upgrading:

  • Check your classpath for jackson-dataformat-xml.
  • If you don’t need XML, exclude the dependency.
  • If you do, configure spring.mvc.contentnegotiation.default-content-type=application/json to keep JSON as the default.

This ensures consistent behavior and prevents XML from taking over your APIs unintentionally.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Recent comments