Closed sandwwraith closed 4 years ago
As far as I can see, current changes solve only @ContextualSerialization
problem and do nothing with Generic serialization.
Suppose you want to formalize responses in a way like this:
@Serializable
data class APIResponse<T>(
val result: T,
val code: Int = 200,
val success: Boolean = true
)
In that situation serializer of APIResponse
would have an argument, in order to implicitly declare nested serializer:
val serializer = APIResponse.serializer(ContentReview.serializer())
And by calling call.respond
you would receive Can't locate argument-less serializer for class APIResponse
, since with the current approach module.getContextual(value::class)
returns null.
Please consider specifying serializer to use in call.respond
in some way other than module.getContextual(...)
.
@e5l This issue is not resolved, and should not be closed. The main feature request here was:
... it is a responsibility of client to pass correct serializer ... This becomes an issue for ktor, where call.respond does not have an option to specify the serializer.
We have a similar issue with call.receive
. No serializer can be retrieved through the type, since the type being deserialized is a star-projected type. We use a custom serializer which can perfectly deal with that. But, ktor prevents us from passing said custom serializer.
Registration as contextual
in the SerializersModule
can't solve that problem for us as far as I know.
If I understand correctly, call.respond
and call.receive
of ktor retrieve the statically defined serializer for the type parameter through KType
. This may be convenient if (1) this serializer can be retrieved statically, and (2) it is the serializer you want. But, in essence, there is a one to many relationship between types and serializers. There will always be a need to be able to override the serializer to use. Retrieving a default serializer through the type parameter should be considered syntactic sugar, not the only possible behavior.
Our current workaround is simply to receive a String
, and initialize the Json
serializer ourselves, passing the custom serializer which ktor doesn't allow us to.
If you are using Mongodb with Ktor you will find that ObjectId (mongodb primary key) doesn't have Kotlin native serializer...
This is an old issue, but I don't see why that would be relevant re-reading what I wrote back then. Is this a comment on something I wrote, or reaffirming there is a need for the original reported issue?
Regardless, we implemented our own format to serialize to BSON using kotlinx.serialization, which does support ObjectId
. Supporting different formats seems unrelated to what I commented on above which is about serializers (which can operate on any format).
@Whathecode This is a need also from my side that this issue activates again. And waw I admire that you guys did write your own serialization, I wasn't aware about that.
Subsystem Client and Server, kotlinx-serialization integration
Is your feature request related to a problem? Please describe. The issue originally described here: https://stackoverflow.com/questions/61492364/serialize-a-maplocaldate-object-with-ktor-and-kotlinx-serialization
When type annotated for contextual serialization inside another serializable type, there is no problem: kotlinx.serialization plugin automatically recognizes it and generates correct code that performs runtime lookup in
SerialModule
.However, when such a type occurs on top-level position / generic position, it is a responsibility of client to pass correct serializer: e.g. in case of serializing
LocalDate
orMap<LocalDate, String>
, kotlinx.serialization expects that user will call correspondingJson.stringify(ContextualSerializer(LocalDate::class))
orJson.stringify(MapSerializer(LocalDateSerializer(), String.serializer())
.This becomes an issue for ktor, where
call.respond
does not have an option to specify the serializer.Describe the solution you'd like
SerialModule
in kotlinx.serialization providescontextualOrDefault
method which may be used in such cases, how it used in serial implicits, e.g. https://github.com/Kotlin/kotlinx.serialization/blob/ee4d7c7215e7ee851be1ccd833f03147820d2bf9/runtime/commonMain/src/kotlinx/serialization/SerialImplicits.kt#L63. This method has one drawback: It performs lookup regardless of any annotations on the type.Another solution may be to somehow allow specifying serializer to use in call.respond, via e.g. a global map of serializers.