mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-02 07:19:01 +00:00
Consider Jackson 2 in HTTP codec auto-config
See gh-47688
This commit is contained in:
committed by
Phillip Webb
parent
7b60227f41
commit
eb5cb2d4e1
@@ -31,6 +31,7 @@ dependencies {
|
||||
optional(project(":core:spring-boot-autoconfigure"))
|
||||
optional(project(":core:spring-boot-test"))
|
||||
optional(project(":module:spring-boot-jackson"))
|
||||
optional(project(":module:spring-boot-jackson2"))
|
||||
optional("org.springframework:spring-webflux")
|
||||
|
||||
testImplementation(project(":core:spring-boot-test"))
|
||||
|
||||
+49
-4
@@ -16,18 +16,22 @@
|
||||
|
||||
package org.springframework.boot.http.codec.autoconfigure;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.PropertyMapper;
|
||||
import org.springframework.boot.http.codec.CodecCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -43,14 +47,17 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||
* {@link org.springframework.core.codec.Decoder Decoders}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(afterName = "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration")
|
||||
@AutoConfiguration(afterName = { "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration",
|
||||
"org.springframework.boot.jackson2.autoconfigure.Jackson2AutoConfiguration" })
|
||||
@ConditionalOnClass({ CodecConfigurer.class, WebClient.class })
|
||||
public final class CodecsAutoConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(ObjectMapper.class)
|
||||
@ConditionalOnClass(JsonMapper.class)
|
||||
@ConditionalOnProperty(name = "spring.http.codecs.preferred-json-mapper", havingValue = "jackson",
|
||||
matchIfMissing = true)
|
||||
static class JacksonJsonCodecConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -66,6 +73,26 @@ public final class CodecsAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(ObjectMapper.class)
|
||||
@Conditional(NoJacksonOrJackson2Preferred.class)
|
||||
@Deprecated(since = "4.0.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
static class Jackson2JsonCodecConfiguration {
|
||||
|
||||
@Bean
|
||||
@Order(0)
|
||||
@ConditionalOnBean(ObjectMapper.class)
|
||||
CodecCustomizer jackson2CodecCustomizer(ObjectMapper objectMapper) {
|
||||
return (configurer) -> {
|
||||
CodecConfigurer.DefaultCodecs defaults = configurer.defaultCodecs();
|
||||
defaults.jacksonJsonDecoder(new org.springframework.http.codec.json.Jackson2JsonDecoder(objectMapper));
|
||||
defaults.jacksonJsonEncoder(new org.springframework.http.codec.json.Jackson2JsonEncoder(objectMapper));
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(HttpCodecsProperties.class)
|
||||
static class DefaultCodecsConfiguration {
|
||||
@@ -104,4 +131,22 @@ public final class CodecsAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static class NoJacksonOrJackson2Preferred extends AnyNestedCondition {
|
||||
|
||||
NoJacksonOrJackson2Preferred() {
|
||||
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingClass("tools.jackson.databind.json.JsonMapper")
|
||||
static class NoJackson {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnProperty(name = "spring.http.codecs.preferred-json-mapper", havingValue = "jackson2")
|
||||
static class Jackson2Preferred {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+27
-3
@@ -1,4 +1,28 @@
|
||||
{
|
||||
"groups": [],
|
||||
"properties": []
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.http.codecs.preferred-json-mapper",
|
||||
"type": "java.lang.String",
|
||||
"defaultValue": "jackson",
|
||||
"description": "Preferred JSON mapper to use for HTTP encoding and decoding. By default, auto-detected according to the environment. Supported values are 'jackson' and 'jackson2' (deprecated)."
|
||||
}
|
||||
],
|
||||
"hints": [
|
||||
{
|
||||
"name": "spring.http.codecs.preferred-json-mapper",
|
||||
"values": [
|
||||
{
|
||||
"value": "jackson"
|
||||
},
|
||||
{
|
||||
"value": "jackson2"
|
||||
}
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "any"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+44
-1
@@ -18,11 +18,13 @@ package org.springframework.boot.http.codec.autoconfigure;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.http.codec.CodecCustomizer;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -72,7 +74,7 @@ class CodecsAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void jacksonCodecCustomizerBacksOffWhenThereIsNoObjectMapper() {
|
||||
void jacksonCodecCustomizerBacksOffWhenThereIsNoJsonMapper() {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean("jacksonCodecCustomizer"));
|
||||
}
|
||||
|
||||
@@ -82,6 +84,37 @@ class CodecsAutoConfigurationTests {
|
||||
.run((context) -> assertThat(context).hasBean("jacksonCodecCustomizer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated(since = "4.0.0", forRemoval = true)
|
||||
void jacksonCodecCustomizerBacksOffWhenJackson2IsPreferred() {
|
||||
this.contextRunner.withUserConfiguration(JsonMapperConfiguration.class)
|
||||
.withPropertyValues("spring.http.codecs.preferred-json-mapper=jackson2")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("jacksonCodecCustomizer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated(since = "4.0.0", forRemoval = true)
|
||||
void jackson2CodecCustomizerIsAutoConfiguredWhenObjectMapperIsPresentAndJackson2IsPreferred() {
|
||||
this.contextRunner.withUserConfiguration(ObjectMapperConfiguration.class)
|
||||
.withPropertyValues("spring.http.codecs.preferred-json-mapper=jackson2")
|
||||
.run((context) -> assertThat(context).hasBean("jackson2CodecCustomizer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated(since = "4.0.0", forRemoval = true)
|
||||
void jackson2CodecCustomizerIsAutoConfiguredWhenObjectMapperIsPresentAndJacksonIsMissing() {
|
||||
this.contextRunner.withUserConfiguration(ObjectMapperConfiguration.class)
|
||||
.withClassLoader(new FilteredClassLoader(JsonMapper.class.getPackage().getName()))
|
||||
.run((context) -> assertThat(context).hasBean("jackson2CodecCustomizer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated(since = "4.0.0", forRemoval = true)
|
||||
void jackson2CodecCustomizerBacksOffWhenJackson2IsPreferredButThereIsNoObjectMapper() {
|
||||
this.contextRunner.withPropertyValues("spring.http.codecs.preferred-json-mapper=jackson2")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("jackson2CodecCustomizer"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void userProvidedCustomizerCanOverrideJacksonCodecCustomizer() {
|
||||
this.contextRunner.withUserConfiguration(JsonMapperConfiguration.class, CodecCustomizerConfiguration.class)
|
||||
@@ -116,6 +149,16 @@ class CodecsAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ObjectMapperConfiguration {
|
||||
|
||||
@Bean
|
||||
ObjectMapper objectMapper() {
|
||||
return new ObjectMapper();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CodecCustomizerConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user