How to Configure Kotlinx Serialization in Spring Boot MVC Rest Client
The Kotlinx Serialization is a powerful and efficient library for serializing and deserializing Kotlin objects. In this tutorial, we'll learn how to configure it for use with RestClient. 1. Add dependencies Check the latest version Kotlinx serialization plugin plugins { ... kotlin("plugin.serialization") version "2.1.0" } Check the latest version Kotlin serialization library dependecies { ... implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0") } 2. Create a MessageConverter configuration import kotlinx.serialization.json.Json import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.http.MediaType import org.springframework.http.converter.KotlinSerializationStringHttpMessageConverter import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter @Configuration class KtxConfig { @Bean fun ktxMessageConverter() : KotlinSerializationJsonHttpMessageConverter { // if you want to ignore unknown keys from json string, // otherwise make sure your data class has all json keys. val json = Json { ignoreUnknownKeys = true } return KotlinSerializationJsonHttpMessageConverter(json) } @Bean fun ktxMessageConverterWithMediaType() : KotlinSerializationStringHttpMessageConverter { // if you want to ignore unknown keys from json string, // otherwise make sure your data class has all json keys. val json = Json { ignoreUnknownKeys = true } return object : KotlinSerializationStringHttpMessageConverter(json, MediaType.TEXT_HTML, MediaType("text", "html")){} } } 3. Create a serializable Data Class import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class ZipCode( @SerialName("cep") val zipCode: String, @SerialName("logradouro") val street: String, @SerialName("uf") val stateAcron: String, @SerialName("estado") val state: String, @SerialName("regiao") val region: String, ) In this example I'm using a ZipCode JSON free API ViaCep 4. Setup your RestClient object import com.ktxserializationrestclientspringboot.beans.KtxConfig import com.ktxserializationrestclientspringboot.json.ZipCode import org.springframework.stereotype.Component import org.springframework.web.client.RestClient @Component class ViaCepGateway( private val ktxConfig: KtxConfig ) : ZipCodeGateway { private val restClient: RestClient = RestClient.builder() .messageConverters { it.add(0, ktxConfig.ktxMessageConverter()) it.add(1, ktxConfig.ktxMessageConverterWithMediaType()) } .baseUrl("https://viacep.com.br/ws/") .build() override fun getInfoCep(cep: String): ZipCode? { return restClient.get() .uri("/{cep}/json", cep) .retrieve() .onStatus({ it.is4xxClientError || it.is5xxServerError }, {_, response -> throw RuntimeException("Fail to find $cep informations. status code: ${response.statusCode}") }) .body(ZipCode::class.java) } } In this step make sure you have added the proper MessageConverter .messageConverters { it.add(0, ktxConfig.ktxMessageConverter()) //it.add(1, ktxConfig.ktxMessageConverterWithMediaType()) only one is needed } 5. Call your ZipCodeGateway @Component class MainCommandLineRunner( private val getCep: GetZipCode ): CommandLineRunner { private companion object { val logger: Logger = LoggerFactory.getLogger(MainCommandLineRunner::class.java) } override fun run(vararg args: String?) { val zipCodeInfo = getCep.execute("01001000") logger.info(zipCodeInfo.toString()) } } Output should be like ZipCode(zipCode=01001-000, street=Praça da Sé, stateAcron=SP, state=São Paulo, region=Sudeste) Bonus If you need to convert the RestClient's response to a list of entities, you'll need to use the ParameterizedTypeReference interface like this: return restClient.get() ... .body(object : ParameterizedTypeReference() {}) The complete implementation is available here. Feel free to explore and try it out!

The Kotlinx Serialization is a powerful and efficient library for serializing and deserializing Kotlin objects. In this tutorial, we'll learn how to configure it for use with RestClient.
1. Add dependencies
Check the latest version Kotlinx serialization plugin
plugins {
...
kotlin("plugin.serialization") version "2.1.0"
}
Check the latest version Kotlin serialization library
dependecies {
...
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
}
2. Create a MessageConverter configuration
import kotlinx.serialization.json.Json
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.http.converter.KotlinSerializationStringHttpMessageConverter
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter
@Configuration
class KtxConfig {
@Bean
fun ktxMessageConverter() : KotlinSerializationJsonHttpMessageConverter {
// if you want to ignore unknown keys from json string,
// otherwise make sure your data class has all json keys.
val json = Json { ignoreUnknownKeys = true }
return KotlinSerializationJsonHttpMessageConverter(json)
}
@Bean
fun ktxMessageConverterWithMediaType() : KotlinSerializationStringHttpMessageConverter<Json> {
// if you want to ignore unknown keys from json string,
// otherwise make sure your data class has all json keys.
val json = Json { ignoreUnknownKeys = true }
return object : KotlinSerializationStringHttpMessageConverter<Json>(json, MediaType.TEXT_HTML, MediaType("text", "html")){}
}
}
3. Create a serializable Data Class
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ZipCode(
@SerialName("cep")
val zipCode: String,
@SerialName("logradouro")
val street: String,
@SerialName("uf")
val stateAcron: String,
@SerialName("estado")
val state: String,
@SerialName("regiao")
val region: String,
)
In this example I'm using a ZipCode JSON free API ViaCep
4. Setup your RestClient object
import com.ktxserializationrestclientspringboot.beans.KtxConfig
import com.ktxserializationrestclientspringboot.json.ZipCode
import org.springframework.stereotype.Component
import org.springframework.web.client.RestClient
@Component
class ViaCepGateway(
private val ktxConfig: KtxConfig
) : ZipCodeGateway {
private val restClient: RestClient = RestClient.builder()
.messageConverters {
it.add(0, ktxConfig.ktxMessageConverter())
it.add(1, ktxConfig.ktxMessageConverterWithMediaType())
}
.baseUrl("https://viacep.com.br/ws/")
.build()
override fun getInfoCep(cep: String): ZipCode? {
return restClient.get()
.uri("/{cep}/json", cep)
.retrieve()
.onStatus({ it.is4xxClientError || it.is5xxServerError }, {_, response ->
throw RuntimeException("Fail to find $cep informations. status code: ${response.statusCode}")
})
.body(ZipCode::class.java)
}
}
In this step make sure you have added the proper MessageConverter
.messageConverters {
it.add(0, ktxConfig.ktxMessageConverter())
//it.add(1, ktxConfig.ktxMessageConverterWithMediaType()) only one is needed
}
5. Call your ZipCodeGateway
@Component
class MainCommandLineRunner(
private val getCep: GetZipCode
): CommandLineRunner {
private companion object {
val logger: Logger = LoggerFactory.getLogger(MainCommandLineRunner::class.java)
}
override fun run(vararg args: String?) {
val zipCodeInfo = getCep.execute("01001000")
logger.info(zipCodeInfo.toString())
}
}
Output should be like
ZipCode(zipCode=01001-000, street=Praça da Sé, stateAcron=SP, state=São Paulo, region=Sudeste)
Bonus
If you need to convert the RestClient's response to a list of entities, you'll need to use the ParameterizedTypeReference interface like this:
return restClient.get()
...
.body(object : ParameterizedTypeReference<List<YOUR_CLASS>>() {})
The complete implementation is available here. Feel free to explore and try it out!