Summary
ServerResponse.BodyBuilder.bodyValueAndAwait
API is broken when it is used with an application it
uses for serialization the kotlinx.serialization
library and the provided body uses generics.
The library is unable to serialize the body since it is a type of Any
and spring falls back
to default one. This could lead to unexpected responses.
For example:
@Serializable
data class SomeBody(@SerialName("user_id") val userId: Int, val name: String)
suspend fun returnBody(request: ServerRequest): ServerResponse {
return ServerResponse
.ok()
// Note: `fun ServerResponse.BodyBuilder.bodyValueAndAwait(body: Any)`
// is not a reified function and is subject to type erasure.
// In cases where response is a collection, the object is serialized as `Collection<Any>`,
// and the response does not have the proper format, which is not expected.
// Actual response: [{"userId":1,"name":"name"}]
// Expected response : [{"user_id":1,"name":"name"}]
.bodyValueAndAwait(listOf(SomeBody(1, "name")))
}
A minimum reproducible example can be found here.
Proposal
Make BodyBuilder.bodyValueAndAwait() a reified type of function. We can also migrate the API without breaking existing functionality.
Alternatives
Only document the behavior and accept it as the intended behavior.
Comment From: GeorgePap-719
Sorry for force-push while in-review. Minor changes in KDocs and error message.
Comment From: sdeleuze
After a deeper look, I am going to implement this feature differently on both Java and Kotlin side via #32713 which supersedes this issue.