Skip to content

Commit 78f9e3b

Browse files
committed
Introduce Kotlin Serialization auto-configuration
See #44241 Signed-off-by: Dmitry Sulman <[email protected]>
1 parent 7379ada commit 78f9e3b

File tree

24 files changed

+1016
-9
lines changed

24 files changed

+1016
-9
lines changed

buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ private void mailPrefixes(Config config) {
118118
private void jsonPrefixes(Config config) {
119119
config.accept("spring.jackson");
120120
config.accept("spring.gson");
121+
config.accept("spring.kotlin-serialization");
121122
}
122123

123124
private void dataPrefixes(Config config) {

documentation/spring-boot-docs/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ dependencies {
122122
autoConfiguration(project(path: ":module:spring-boot-jooq", configuration: "autoConfigurationMetadata"))
123123
autoConfiguration(project(path: ":module:spring-boot-jsonb", configuration: "autoConfigurationMetadata"))
124124
autoConfiguration(project(path: ":module:spring-boot-kafka", configuration: "autoConfigurationMetadata"))
125+
autoConfiguration(project(path: ":module:spring-boot-kotlin-serialization", configuration: "autoConfigurationMetadata"))
125126
autoConfiguration(project(path: ":module:spring-boot-ldap", configuration: "autoConfigurationMetadata"))
126127
autoConfiguration(project(path: ":module:spring-boot-liquibase", configuration: "autoConfigurationMetadata"))
127128
autoConfiguration(project(path: ":module:spring-boot-mail", configuration: "autoConfigurationMetadata"))
@@ -212,6 +213,7 @@ dependencies {
212213
configurationProperties(project(path: ":module:spring-boot-jooq", configuration: "configurationPropertiesMetadata"))
213214
configurationProperties(project(path: ":module:spring-boot-jpa", configuration: "configurationPropertiesMetadata"))
214215
configurationProperties(project(path: ":module:spring-boot-kafka", configuration: "configurationPropertiesMetadata"))
216+
configurationProperties(project(path: ":module:spring-boot-kotlin-serialization", configuration: "configurationPropertiesMetadata"))
215217
configurationProperties(project(path: ":module:spring-boot-ldap", configuration: "configurationPropertiesMetadata"))
216218
configurationProperties(project(path: ":module:spring-boot-liquibase", configuration: "configurationPropertiesMetadata"))
217219
configurationProperties(project(path: ":module:spring-boot-mail", configuration: "configurationPropertiesMetadata"))

documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/features/json.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Spring Boot provides integration with three JSON mapping libraries:
66
- Gson
77
- Jackson
88
- JSON-B
9+
- Kotlin Serialization
910

1011
Jackson is the preferred and default library.
1112

@@ -68,3 +69,12 @@ To take more control, one or more javadoc:org.springframework.boot.autoconfigure
6869
Auto-configuration for JSON-B is provided.
6970
When the JSON-B API and an implementation are on the classpath a javadoc:jakarta.json.bind.Jsonb[] bean will be automatically configured.
7071
The preferred JSON-B implementation is Eclipse Yasson for which dependency management is provided.
72+
73+
74+
75+
[[features.json.kotlin-serialization]]
76+
== Kotlin Serialization
77+
78+
Auto-configuration for Kotlin Serialization is provided.
79+
When `kotlinx-serialization-json` is on the classpath a https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-json/kotlinx.serialization.json/-json/[Json] bean is automatically configured.
80+
Several `+spring.kotlin-serialization.*+` configuration properties are provided for customizing the configuration.

module/spring-boot-autoconfigure-classic-modules/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ dependencies {
157157
api(project(":module:spring-boot-kafka")) {
158158
transitive = false
159159
}
160+
api(project(":module:spring-boot-kotlin-serialization")) {
161+
transitive = false
162+
}
160163
api(project(":module:spring-boot-ldap")) {
161164
transitive = false
162165
}

module/spring-boot-http-converter/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
optional(project(":module:spring-boot-gson"))
3535
optional(project(":module:spring-boot-jackson"))
3636
optional(project(":module:spring-boot-jsonb"))
37+
optional(project(":module:spring-boot-kotlin-serialization"))
3738
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
3839
optional("com.google.code.gson:gson")
3940
optional("jakarta.json.bind:jakarta.json.bind-api")

module/spring-boot-http-converter/src/main/java/org/springframework/boot/http/converter/autoconfigure/GsonHttpMessageConvertersConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ static class JsonbPreferred {
9191

9292
}
9393

94+
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY,
95+
havingValue = "kotlin-serialization")
96+
static class KotlinxSerialization {
97+
98+
}
99+
94100
}
95101

96102
}

module/spring-boot-http-converter/src/main/java/org/springframework/boot/http/converter/autoconfigure/HttpMessageConverters.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>>
7171
MultiValueMap<Class<?>, Class<?>> equivalentConverters = new LinkedMultiValueMap<>();
7272
putIfExists(equivalentConverters, "org.springframework.http.converter.json.JacksonJsonHttpMessageConverter",
7373
"org.springframework.http.converter.json.MappingJackson2HttpMessageConverter",
74-
"org.springframework.http.converter.json.GsonHttpMessageConverter");
74+
"org.springframework.http.converter.json.GsonHttpMessageConverter",
75+
"org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter");
7576
putIfExists(equivalentConverters, "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter",
76-
"org.springframework.http.converter.json.GsonHttpMessageConverter");
77+
"org.springframework.http.converter.json.GsonHttpMessageConverter",
78+
"org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter");
7779
EQUIVALENT_CONVERTERS = CollectionUtils.unmodifiableMultiValueMap(equivalentConverters);
7880
}
7981

module/spring-boot-http-converter/src/main/java/org/springframework/boot/http/converter/autoconfigure/HttpMessageConvertersAutoConfiguration.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@
4545
* @author Sebastien Deleuze
4646
* @author Stephane Nicoll
4747
* @author Eddú Meléndez
48+
* @author Dmitry Sulman
4849
* @since 4.0.0
4950
*/
5051
@AutoConfiguration(afterName = { "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration",
5152
"org.springframework.boot.jsonb.autoconfigure.JsonbAutoConfiguration",
52-
"org.springframework.boot.gson.autoconfigure.GsonAutoConfiguration" })
53+
"org.springframework.boot.gson.autoconfigure.GsonAutoConfiguration",
54+
"org.springframework.boot.kotlin.serialization.autoconfigure.KotlinSerializationAutoConfiguration" })
5355
@ConditionalOnClass(HttpMessageConverter.class)
5456
@Conditional(NotReactiveWebApplicationCondition.class)
5557
@Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class,
56-
JsonbHttpMessageConvertersConfiguration.class })
58+
JsonbHttpMessageConvertersConfiguration.class, KotlinSerializationHttpMessageConvertersConfiguration.class })
5759
public final class HttpMessageConvertersAutoConfiguration {
5860

5961
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";

module/spring-boot-http-converter/src/main/java/org/springframework/boot/http/converter/autoconfigure/JsonbHttpMessageConvertersConfiguration.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
26+
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
2627
import org.springframework.context.annotation.Bean;
2728
import org.springframework.context.annotation.Conditional;
2829
import org.springframework.context.annotation.Configuration;
@@ -65,10 +66,33 @@ static class JsonbPreferred {
6566

6667
}
6768

69+
@Conditional(JacksonAndGsonAndKotlinSerializationMissingCondition.class)
70+
static class JacksonAndGsonAndKotlinSerializationMissing {
71+
72+
}
73+
74+
}
75+
76+
private static class JacksonAndGsonAndKotlinSerializationMissingCondition extends NoneNestedConditions {
77+
78+
JacksonAndGsonAndKotlinSerializationMissingCondition() {
79+
super(ConfigurationPhase.REGISTER_BEAN);
80+
}
81+
6882
@SuppressWarnings("removal")
69-
@ConditionalOnMissingBean({ org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.class,
70-
GsonHttpMessageConverter.class })
71-
static class JacksonAndGsonMissing {
83+
@ConditionalOnBean(org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.class)
84+
static class JacksonAvailable {
85+
86+
}
87+
88+
@ConditionalOnBean(GsonHttpMessageConverter.class)
89+
static class GsonAvailable {
90+
91+
}
92+
93+
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY,
94+
havingValue = "kotlin-serialization")
95+
static class KotlinxPreferred {
7296

7397
}
7498

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.http.converter.autoconfigure;
18+
19+
import kotlinx.serialization.json.Json;
20+
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
25+
import org.springframework.context.annotation.Bean;
26+
import org.springframework.context.annotation.Configuration;
27+
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
28+
29+
/**
30+
* Configuration for HTTP message converters that use Kotlin Serialization.
31+
*
32+
* @author Dmitry Sulman
33+
*/
34+
@Configuration(proxyBeanMethods = false)
35+
@ConditionalOnClass(Json.class)
36+
class KotlinSerializationHttpMessageConvertersConfiguration {
37+
38+
@Configuration(proxyBeanMethods = false)
39+
@ConditionalOnBean(Json.class)
40+
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY,
41+
havingValue = "kotlin-serialization")
42+
static class KotlinSerializationHttpMessageConverterConfiguration {
43+
44+
@Bean
45+
@ConditionalOnMissingBean
46+
KotlinSerializationJsonHttpMessageConverter kotlinSerializationJsonHttpMessageConverter(Json json) {
47+
return new KotlinSerializationJsonHttpMessageConverter(json);
48+
}
49+
50+
}
51+
52+
}

0 commit comments

Comments
 (0)