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