SMILEY4 / ktor-swagger-ui

Kotlin Ktor plugin to generate OpenAPI and provide Swagger UI
Apache License 2.0
150 stars 25 forks source link

[Question] automatic nullable? #72

Closed clragon closed 9 months ago

clragon commented 9 months ago

Pre-amble: I am quite new to Kotlin, so I might be missing something very obvious.

We assume I have the following model:

data class User(
    val name: String,
    val pronouns: String? = null,
)

In the model we can see that a User has a name which is a String and pronouns which is a String or Null.

However, in the Swagger.json, we see:

"User" : {
  "type" : "object",
  "properties" : {
    "name" : {
      "type" : "string"
    },
    "pronouns" : {
      "type" : "string"
    }
  }
},

We can spot that pronouns was not marked as "nullable": true.

In the Example section in SchemaAnnotations we can see:

    @field:Schema(description = "the age of the person in years", nullable = true)
    val age: Int

which defines a property age which is Int. However, the schema annotation marks it as nullable, meaning it is actually Int or Null.

I dont quite understand this disconnect.

  1. Why are fields which can be null in Kotlin not marked as nullable in the Swagger.json?
  2. Why does this example mark a field that can not be null as nullable?

From what I understand, the nullable annotation should transform the type of a field from Type to Type?. Has this behaviour just not been implemented in the ktor-swagger-ui package or am I misunderstanding something?

SMILEY4 commented 9 months ago

Hi,

  1. Why does this example mark a field that can not be null as nullable?

No real technical reason, just a mistake on my side. Annotating a non-nullable field as nullable does not make sense. The annotation only affects the schema and has no effect on the "real" logic/model. Thanks for the hint - i'll change it.

  1. Why are fields which can be null in Kotlin not marked as nullable in the Swagger.json?

Classes are transformed into a json-schema using a another library, which is written in java, so it probaby doesnt know the difference between a nullable and a non-nullable field and can't automatically detect it itself.

Regarding the automatic detection of nullable fields, i think its possible to extend the schema-generator with custom modules/addons. This way i should be able add the nullable-detection "relativly" easily - i'll look into that.

SMILEY4 commented 9 months ago

After some reasearch, i dont think automatic detection of nullable fields is easily possible with the current setup. The json-schemas are generated with the help of Java's reflection, so all information specific to kotlin is lost. I'll leave it as is for now, though i may have an idea for the future ;)

clragon commented 6 months ago

Thank you for looking into it. This certainly throws a wrench into my machinations but I suppose there is nothing we can do.

clragon commented 6 months ago

I have worked around this by painstakingly marking all fields by hand:

data class User(
    @field:Schema(required = true)
    val id: Int,
    @field:Schema(required = true)
    val name: String,
    @field:Schema(required = true)
    val rank: UserRank,
    @field:Schema(required = true)
    val strikes: Int,
    @field:Schema(required = true)
    val isBanned: Boolean,
)

data class UserUpdate(
    @field:Schema(nullable = true)
    val name: String? = null,
    @field:Schema(nullable = true)
    val rank: UserRank? = null,
    @field:Schema(nullable = true)
    val strikes: Int? = null,
    @field:Schema(nullable = true)
    val isBanned: Boolean? = null,
)

With this setup, my Models actually generate correctly with the openapi-generator. This is better than wrong typing at least.