I'm building a Spring WebFlux API with Kotlin and using Kotlinx Serialization for JSON serialization.
build.gradle.kts
plugins {
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.spring)
alias(libs.plugins.spring.boot)
alias(libs.plugins.spring.dependency.management)
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webflux:3.5.3")
{
exclude(group = "com.fasterxml.jackson.core", module = "jackson-databind")
exclude(group = "com.fasterxml.jackson.module", module = "jackson-module-kotlin")
}
implementation(libs.kotlinX.serialization)
}
libs.version.toml-
[versions]
spring = "3.5.3"
kotlin = "2.2.0"
serialization = "1.9.0"
kotlinX-serialization = {module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
spring-boot = { id = "org.springframework.boot", version.ref = "spring" }
spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.7" }
My controller method looks like this:
@GetMapping("/trainSch", produces = [MediaType.APPLICATION_JSON_VALUE])
suspend fun getTrainSch(
@RequestParam("trainNo") trainNumber: String
): ResponseEntity<TrainDetails> {
return ResponseEntity.ok(
TrainDetails(
no = trainNumber,
na = "Superfast Express",
typ = 1,
zn = 5,
dly = 10,
rake = "LHB",
classes = 3,
upd = "10:45 AM"
)
)
}
TrainDetails is a Kotlin data class:
@Serializable
data class TrainDetails(
val no: String,
val na: String,
val typ: Int,
val zn: Int,
val dly: Int,
val rake: String,
val classes: Int,
val upd: String
)
I have registered the Kotlinx Serialization encoder/decoder with a WebFluxConfigurer bean:
@Bean
fun webFluxConfigurer(
encoder: KotlinSerializationJsonEncoder,
decoder: KotlinSerializationJsonDecoder
): WebFluxConfigurer = object : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
configurer.defaultCodecs().kotlinSerializationJsonEncoder(encoder)
configurer.defaultCodecs().kotlinSerializationJsonDecoder(decoder)
}
}
Problem: When I make a GET request to /trainSch?trainNo=12345, the debug logs show:
TRACE ... CharSequenceEncoder : Writing "{\"no\":\"12345\",\"na\":\"Superfast Express\",...}"
Instead of:
TRACE ... KotlinSerializationJsonEncoder : Writing {...}
It seems Spring is using CharSequenceEncoder (which encodes Strings) instead of my Kotlinx JSON encoder.
Response in Postman-
Content-Type:application/json
content-encoding:gzip
content-length:123
{
"no": "12232",
"na": "Superfast Express",
"typ": 1,
"dly": 10,
"zn": 5,
"rake": "LHB",
"classes": 3,
"upd": "10:45 AM"
}