spring-framework
spring-framework copied to clipboard
Provide a way to configure KotlinSerializationJsonDecoder
It seems there isn't a way to provide a custom Json
or set config on Json
for the KotlinSerializationJsonDecoder
Spring Framework 5.3.14
Workaround:
@Configuration(proxyBeanMethods = false)
class InitConfiguration {
@ExperimentalSerializationApi
@Bean
fun kotlinSerializationJsonDecoder() = KotlinSerializationJsonDecoder(Json {
explicitNulls = false
})
}
@ExperimentalSerializationApi
@Configuration
class WebConfig(val decoder: KotlinSerializationJsonDecoder) : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
super.configureHttpMessageCodecs(configurer)
configurer.defaultCodecs().kotlinSerializationJsonDecoder(decoder)
}
}
I don't think the decoder needs to be a bean so the config could be simplified, and the result would be how this should be done. So it is possible but maybe you are expecting a method for this on CodecConfigurer.DefaultCodecs
? The number of methods there would explode if we added options at this level, and more importantly it would force classpath dependencies that are otherwise optional.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
I think you are right about the unnecessary bean but I guess I was hoping for something like Jackson2ObjectMapperBuilderCustomizer
which provides a nice way to customize Jackson.
I tried the same thing as james (without success, obviously):
@Configuration
@EnableWebFlux
class JsonConfiguration : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
val decoder = KotlinSerializationJsonDecoder(Json { ignoreUnknownKeys = true })
configurer.defaultCodecs().kotlinSerializationJsonDecoder(decoder)
}
}
The configuration is called, but the configured KotlinSerializationJsonDecoder is not used for deserialization in an annotated rest service. It is always Json.Default being used.
It seems there isn't a way to provide a custom
Json
or set config onJson
for theKotlinSerializationJsonDecoder
Spring Framework 5.3.14
Workaround:
@Configuration(proxyBeanMethods = false) class InitConfiguration { @ExperimentalSerializationApi @Bean fun kotlinSerializationJsonDecoder() = KotlinSerializationJsonDecoder(Json { explicitNulls = false }) } @ExperimentalSerializationApi @Configuration class WebConfig(val decoder: KotlinSerializationJsonDecoder) : WebFluxConfigurer { override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) { super.configureHttpMessageCodecs(configurer) configurer.defaultCodecs().kotlinSerializationJsonDecoder(decoder) } }
@jamesward Thanks for sharing your workaround. Unfortunately had no luck yet in doing the same.
+1 on this request. It would be great to have some customization option, perhaps properties also available at JSON Properties
but something similar to Jackson2ObjectMapperBuilderCustomizer
would be nice for this purpose as well.
I was wondering if @sdeleuze has any thoughts on this.
I just realized that for what I wanted to do I had to take a different approach. I wanted to configure the kotlinx.serialization
Decoder for WebClient
.
I ended up with something close to this:
object KSerializationConfig {
val json = Json {
ignoreUnknownKeys = true
isLenient = true
allowSpecialFloatingPointValues = true
useArrayPolymorphism = true
encodeDefaults = true
explicitNulls = false
}
}
@Bean
fun apiClient() = WebClient.builder()
.baseUrl("${apiProperties.baseUrl}/rest/api")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.codecs {
val decoder = KotlinSerializationJsonDecoder(KSerializationConfig.json)
it.defaultCodecs().kotlinSerializationJsonDecoder(decoder)
}.build()
Based on: https://stackoverflow.com/a/66020393/12249394 and https://discuss.kotlinlang.org/t/kotlinx-serialization-with-spring-boot/16540/15
@knob-creek I tried this and it worked as expected
@Configuration
class JsonConfiguration : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
val json = Json { ignoreUnknownKeys = true }
configurer.defaultCodecs().kotlinSerializationJsonDecoder(KotlinSerializationJsonDecoder(json))
configurer.defaultCodecs().kotlinSerializationJsonEncoder(KotlinSerializationJsonEncoder(json))
}
}
I tend to think this is reasonably concise and discoverable to be usable.
@jamesward I am not against something like Jackson2ObjectMapperBuilderCustomizer
but this is on Spring Boot side not Spring Framework, and I am not sure kotlinx.serialization
is popular enough for the Spring Boot team to accept such dedicated support.
In any case, it looks like to me that this issue can be declined as I don't see something obvious we should do on Framework side.
@sdeleuze Is there a way to configure this if I am not using WebFlux?
If what you want is configuring this with Spring MVC, yes you can customize it via regular converter configuration, which may be a bit more involved than with codecs, but totally doable.
For both WebFlux and MVC, worth to have in mind that https://github.com/Kotlin/kotlinx.serialization/issues/2060 will be required to customize serialization of interface types.