Hello. Is it possible in `ktor-openapi` to specify...
# ktor
r
Hello. Is it possible in
ktor-openapi
to specify a
JsonSchema
for a specific type when configuring
swaggerUI
? For example, I have multiple fields across various models with the
ZonedDateTime
type, which are marked with
@Contextual
. By default, the contextual kind is represented as an
object
, but I would like to define the
JsonSchema
with correct type, format, etc. once and assign it to this type globally.
b
The easiest would probably be to include the
io.ktor.openapi.JsonSchema.Type
annotation on the field. You can also manipulate the
JsonSchema
objects after the inference generates the schema like
jsonSchema<Foo>().copy(properties = mapOf(...))
or when using reflection, you can use a custom
SchemaReflectionAdapter
.
r
I feel like this approach defeats the purpose of
@Contextual
, which allows the same field to be represented by different descriptors in
KSerializer
. Let's say I have a common Gradle module
model
that provides a
Foo
class with a
@Contextual date: ZonedDateTime
field, alongside two separate REST API modules:
server
and
server-analytic
. On the
server
side, I might configure
Json
with a
SerializersModule
that has a contextual serializer resolving
ZonedDateTime
as an ISO string. But on
server-analytic
, the serializer could describe
ZonedDateTime
as an object using
ClassSerialDescriptorBuilder
. So, if I hardcode `JsonSchema.Type`/`JsonSchema.Format` in the model itself, it's not going to match the type and format of a different serializer implementation.
Copy code
// public api
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.STRING)

// internal analytic api
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("ZonedDateTime") {
    element<String>("year")
    element<String>("month")
    element<String>("day")
    // ...
}
b
Ah I see, so for this case, the inference should be able to pick up the correct serializer from the serializer module. Ideally the inference would pick up the serializers module from the content negotiation plugin, but I'm not sure if this is the case. I'll have to check on how to get it working e2e and get back to you, but it should be possible.
I've added a ticket to handle this better https://youtrack.jetbrains.com/issue/KTOR-9590 So in 3.6.0, the serializer module used in the content negotiation plugin will be used automatically. And we'll handle contextual serializers properly.
r
Sounds good for the default behavior. This will provide the correct type, but it still won't allow the use of
@JsonSchema.*
annotations. For instance, in the second example above, if we get the correct representation of
ZonedDateTime
as an object from descriptor, how would I specify these annotations for the
year
field:
Copy code
@JsonSchema.Description("Year in ISO-8601 format")
@JsonSchema.Format("yyyy")
@JsonSchema.Example("1970", "2026")
@JsonSchema.Minimum(1970.0)
Therefore, in addition to this, I would consider the approach used in third-party libraries before the introduction of
ktor-openapi
. For example, in
ktor-openapi-tools
it was called Overwriting types
b
good point, we should provide an easier means of overriding
👍 1