Skip to content

Commit 5928326

Browse files
committed
Introduce Kotlin Serialization auto-configuration
See #44241 Signed-off-by: Dmitry Sulman <[email protected]>
1 parent 0f2e0d6 commit 5928326

File tree

23 files changed

+1014
-9
lines changed

23 files changed

+1014
-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/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+
}

module/spring-boot-http-converter/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"name": "spring.http.converters.preferred-json-mapper",
55
"type": "java.lang.String",
66
"defaultValue": "jackson",
7-
"description": "Preferred JSON mapper to use for HTTP message conversion. By default, auto-detected according to the environment. Supported values are 'jackson', 'gson', and 'jsonb'. When other json mapping libraries (such as kotlinx.serialization) are present, use a custom HttpMessageConverters bean to control the preferred mapper."
7+
"description": "Preferred JSON mapper to use for HTTP message conversion. By default, auto-detected according to the environment. Supported values are 'jackson', 'gson', 'jsonb' and 'kotlin-serialization'. When other json mapping libraries are present, use a custom HttpMessageConverters bean to control the preferred mapper."
88
}
99
],
1010
"hints": [
@@ -19,6 +19,9 @@
1919
},
2020
{
2121
"value": "jsonb"
22+
},
23+
{
24+
"value": "kotlin-serialization"
2225
}
2326
],
2427
"providers": [

0 commit comments

Comments
 (0)