Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to configure KotlinSerializationJsonDecoder #27845

Closed
jamesward opened this issue Dec 22, 2021 · 9 comments
Closed

Provide a way to configure KotlinSerializationJsonDecoder #27845

jamesward opened this issue Dec 22, 2021 · 9 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply theme: kotlin An issue related to Kotlin support

Comments

@jamesward
Copy link

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)
    }
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 22, 2021
@rstoyanchev
Copy link
Contributor

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.

@rstoyanchev rstoyanchev added in: web Issues in web modules (web, webmvc, webflux, websocket) status: waiting-for-feedback We need additional information before we can continue theme: kotlin An issue related to Kotlin support labels Jan 5, 2022
@spring-projects-issues
Copy link
Collaborator

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.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Jan 12, 2022
@jamesward
Copy link
Author

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.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue labels Jan 15, 2022
@knob-creek
Copy link

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.

@albertocavalcante
Copy link

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)
    }
}

@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.

@albertocavalcante
Copy link

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

@sdeleuze sdeleuze self-assigned this Jan 16, 2023
@sdeleuze sdeleuze added in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on in: web Issues in web modules (web, webmvc, webflux, websocket) status: feedback-provided Feedback has been provided labels Jan 16, 2023
@sdeleuze
Copy link
Contributor

@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 sdeleuze closed this as not planned Won't fix, can't repro, duplicate, stale Jan 16, 2023
@987Nabil
Copy link

987Nabil commented Mar 3, 2023

@sdeleuze Is there a way to configure this if I am not using WebFlux?

@sdeleuze
Copy link
Contributor

sdeleuze commented Mar 6, 2023

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 Kotlin/kotlinx.serialization#2060 will be required to customize serialization of interface types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply theme: kotlin An issue related to Kotlin support
Projects
None yet
Development

No branches or pull requests

7 participants