Support for `serializer<@Contextual T>`
The following incomplete code cannot be used because @Contextual doesn't work in serializer<T>() .
This code would allow for very short definitions of server endpoints that handle serialization across multiple Content-Types.
inline fun <reified IN, reified OUT> ServerSystem.postHandler(action: (IN) -> OUT) {
// Get the types for documentation purposes
val inputType = serializer<IN>()
val outputType = serializer<OUT>()
// ... other setup ...
// set up the underlying server library's request handler
handler { request ->
val format = Formats.lookup(headers["Content-Type"])
val input = format.decodeFromBody(inputType, request.body)
val output = action(input)
return@handler HttpResponse(
body = Formats.lookup(headers["Accept"]).encodeToBody(outputType, output)
)
}
}
// ...
val lookup = postHandler { input: @Contextual UUID ->
database.get(input)
}
Attempting to use this crashes because the @Contextual annotation isn't carried through.
println(serializerOrNull(typeOf<@Contextual java.util.UUID>())) // prints null
What I would expect is to get a ContextualSerializer for the type.
The context is registered in the Serializers module, which means you need to provide a customized format. And if a customized format is provided, you may need not the @Contextual here.
@UnknownJoe796 As @xiaozhikang0916 says, you can just look up the serializer from the module. serializerOrNull is for statically determined serializers. Contextual needs a context.
I'm not sure what you are trying to achieve here since a) the @Contextual annotation has meaning only inside the @Serializable class b) ContextualSerializer is never returned from the serializer<T> function since it requires the SerializersModule to work. However, there are serializer<T> extensions on the SerializersModule as well, so I believe you want to do the following:
class Uuid
object UuidSerializer: KSerializer<Uuid> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MyUuid", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Uuid) {
TODO("Not yet implemented")
}
override fun deserialize(decoder: Decoder): Uuid {
TODO("Not yet implemented")
}
}
val myModule = SerializersModule {
contextual(Uuid::class, UuidSerializer)
}
inline fun <reified IN> postHandler(action: (IN) -> Unit) {
println(myModule.serializer<IN>().descriptor)
}
@Test
fun contextualDemo() {
postHandler<Uuid> { } // prints PrimitiveDescriptor(MyUuid)
}