mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Restrict Kotlin serialization when alternative is available
Previously, Kotlin Serialization would be used too aggressively then an alternative JSON converter was available. This could lead to unwanted results when a response should have been serialized using Jackson, for example, rather than Kotlin Serialization. This commit addresses this by only allowing Kotlin Serialization to serialize types that are not annotated with @Serializable when no alternative JSON converter is available. Fixes gh-48070
This commit is contained in:
+20
-2
@@ -19,11 +19,14 @@ package org.springframework.boot.http.converter.autoconfigure;
|
||||
import kotlinx.serialization.Serializable;
|
||||
import kotlinx.serialization.json.Json;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||
|
||||
/**
|
||||
@@ -39,8 +42,23 @@ class KotlinSerializationHttpMessageConvertersConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
KotlinSerializationJsonHttpMessageConverter kotlinSerializationJsonHttpMessageConverter(Json json) {
|
||||
return new KotlinSerializationJsonHttpMessageConverter(json);
|
||||
KotlinSerializationJsonHttpMessageConverter kotlinSerializationJsonHttpMessageConverter(Json json,
|
||||
ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||
return supportsApplicationJson(converters) ? new KotlinSerializationJsonHttpMessageConverter(json)
|
||||
: new KotlinSerializationJsonHttpMessageConverter(json, (type) -> true);
|
||||
}
|
||||
|
||||
private boolean supportsApplicationJson(ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||
return converters.orderedStream().filter(this::supportsApplicationJson).findFirst().isPresent();
|
||||
}
|
||||
|
||||
private boolean supportsApplicationJson(HttpMessageConverter<?> converter) {
|
||||
for (MediaType mediaType : converter.getSupportedMediaTypes()) {
|
||||
if (!mediaType.equals(MediaType.ALL) && mediaType.isCompatibleWith(MediaType.APPLICATION_JSON)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+19
@@ -47,6 +47,7 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.server.mvc.TypeConstrainedJacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
|
||||
@@ -229,6 +230,24 @@ class HttpMessageConvertersAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void kotlinSerializationUsesLimitedPredicateWhenOtherJsonConverterIsAvailable() {
|
||||
allOptionsRunner().run((context) -> {
|
||||
KotlinSerializationJsonHttpMessageConverter converter = context
|
||||
.getBean(KotlinSerializationJsonHttpMessageConverter.class);
|
||||
assertThat(converter.canWrite(Map.class, MediaType.APPLICATION_JSON)).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void kotlinSerializationUsesUnrestrictedPredicateWhenNoOtherJsonConverterIsAvailable() {
|
||||
this.contextRunner.withBean(Json.class, () -> Json.Default).run((context) -> {
|
||||
KotlinSerializationJsonHttpMessageConverter converter = context
|
||||
.getBean(KotlinSerializationJsonHttpMessageConverter.class);
|
||||
assertThat(converter.canWrite(Map.class, MediaType.APPLICATION_JSON)).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringDefaultConverter() {
|
||||
this.contextRunner.run(assertConverter(StringHttpMessageConverter.class, "stringHttpMessageConverter"));
|
||||
|
||||
Reference in New Issue
Block a user