Closed sauterl closed 3 months ago
This plugin is written for Java, not Kotlin - via annotation processor API, not KSP. It means that we only have access to metadata exposed by Java's compiler and it misses most of the Kotlin's metadata - such as built-in nullability support.
The good thing, in terms of this question, is that Kotlin by default annotates these properties with @NotNull
/@Nullable
annotations and we have support for it:
So it should work for you out of the box. Did you notice some issues with these properties? :thinking:
Thanks for the quick reply and the clarification regarding the target language.
I will have to investigate this on a clean slate. In our project, the generated OpenApi Specification was missing the "nullable" : true
, if we didn't specify it with the @OpenApiNullable
annotation. Based on your answer, this is unexpected behaviour.
Unfortunately, I do not recall whether this worked as expected in a previous version of Javalin, the following affects 6.1.3 (which is a couple of minor versions behind latest, I am aware of this). version 6.1.6
.
Specifically, the following ApiClientAnswer
Kotlin data class:
@Serializable
data class ApiClientAnswer( //TODO add optional relevance score field
/** The text that is part of this [ApiClientAnswer]. */
@get:OpenApiNullable
val text: String? = null,
/** The [MediaItemId] associated with the [ApiClientAnswer]. Is usually added as contextual information by the receiving endpoint. */
@JsonIgnore
@get:OpenApiIgnore
val mediaItemId: MediaItemId? = null,
/** The name of the media item that is part of the answer. */
val mediaItemName: String? = null,
/** The name of the collection the media item belongs to. */
val mediaItemCollectionName: String? = null,
/** For temporal [ApiClientAnswer]s: Start of the segment in question in milliseconds. */
val start: Long? = null,
/** For temporal [ApiClientAnswer]s: End of the segment in question in milliseconds. */
val end: Long? = null,
) {}
Produced this OpenApi schema:
"ApiClientAnswer" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"text" : {
"type" : "string"
},
"mediaItemName" : {
"type" : "string"
},
"mediaItemCollectionName" : {
"type" : "string"
},
"start" : {
"type" : "integer",
"format" : "int64"
},
"end" : {
"type" : "integer",
"format" : "int64"
}
}
}
Whereas if annotated with @OpenApiNullable
:
@Serializable
data class ApiClientAnswer( //TODO add optional relevance score field
/** The text that is part of this [ApiClientAnswer]. */
val text: String? = null,
/** The [MediaItemId] associated with the [ApiClientAnswer]. Is usually added as contextual information by the receiving endpoint. */
@JsonIgnore
@get:OpenApiIgnore
val mediaItemId: MediaItemId? = null,
/** The name of the media item that is part of the answer. */
@get:OpenApiNullable
val mediaItemName: String? = null,
/** The name of the collection the media item belongs to. */
@get:OpenApiNullable
val mediaItemCollectionName: String? = null,
/** For temporal [ApiClientAnswer]s: Start of the segment in question in milliseconds. */
@get:OpenApiNullable
val start: Long? = null,
/** For temporal [ApiClientAnswer]s: End of the segment in question in milliseconds. */
@get:OpenApiNullable
val end: Long? = null,
) {}
the generated JSON schema is as expected:
"ApiClientAnswer" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"text" : {
"type" : "string",
"nullable" : true
},
"mediaItemName" : {
"type" : "string",
"nullable" : true
},
"mediaItemCollectionName" : {
"type" : "string",
"nullable" : true
},
"start" : {
"type" : "integer",
"format" : "int64",
"nullable" : true
},
"end" : {
"type" : "integer",
"format" : "int64",
"nullable" : true
}
}
}
EDIT: Updated the javalin dependencies in our project to 6.1.6
and reported investigation.
Well, I was wrong. The Nullable
/NotNull
properties only affects the required
list, it's unrelated to nullable
property.
It should work like that out of the box, you can already try it in 6.1.7-SNAPSHOT :)
Disclaimer: I am not sure whether this is a bug report or a feature request, so I'm just going to ask!
As far as I am aware, nullable properties have to be specifically marked as such, with the
OpenApiNullable
annotation. However, since Kotlin differentiates between nullable and non-nullable types, is there a way to have the plugin automatically inject this into the OpenApi Specification?Or did I miss another approach?
Thanks in advance!