SMILEY4 / ktor-swagger-ui

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

Schema is generated using 3.1 spec, but rendered using spec 3.0 renderer #137

Closed NecroKote closed 1 month ago

NecroKote commented 1 month ago

Hi there! I was investigating https://github.com/SMILEY4/schema-kenerator/issues/28 when I noticed that the 3.0-specific Json object was used to render the schema that is generated as 3.1-compatible https://github.com/SMILEY4/ktor-swagger-ui/blob/b7a73484326a115532f4ea1be5ac3f72b437c156/ktor-swagger-ui/src/main/kotlin/io/github/smiley4/ktorswaggerui/SwaggerPlugin.kt#L104

That causes the mentioned issue and potentially other similar issue of 3.0 being incompatible with 3.1

The fix should be as easy as to replace Json with Json31

rmcmk commented 1 month ago

@NecroKote Just got a chance to test this, and not all is well. Getting some inconsistent behavior.

data class ErrorResponse(
    val statusCode: Int,
    val statusDescription: String,
    val errorMessage: String,
    val requestMetadata: Map<String, String>,
)

3.0 Json.pretty ->

image

      "ErrorResponse" : {
        "title" : "ErrorResponse",
        "required" : [ "errorMessage", "requestMetadata", "statusCode", "statusDescription" ],
        "type" : "object",
        "properties" : {
          "statusCode" : {
            "title" : "Int",
            "type" : "integer",
            "format" : "int32"
          },
          "statusDescription" : {
            "title" : "String",
            "type" : "string"
          },
          "errorMessage" : {
            "title" : "String",
            "type" : "string"
          },
          "requestMetadata" : {
            "title" : "LinkedHashMap_String-String",
            "type" : "object",
            "additionalProperties" : {
              "title" : "String",
              "type" : "string"
            }
          }
        }
      }

3.1 Json31.pretty ->

image

      "ErrorResponse" : {
        "properties" : {
          "statusCode" : {
            "format" : "int32",
            "title" : "Int"
          },
          "statusDescription" : {
            "title" : "String"
          },
          "errorMessage" : {
            "title" : "String"
          },
          "requestMetadata" : {
            "additionalProperties" : {
              "title" : "String"
            },
            "title" : "LinkedHashMap_String-String"
          }
        },
        "required" : [ "errorMessage", "requestMetadata", "statusCode", "statusDescription" ],
        "title" : "ErrorResponse"
      }

Looks like all of my (string | null) types work with 3.1. Looks like regular string types are being stripped from the schema? Strange.

data class RpcDefinition(
    val vendor: String,
    val http: Uri,
    val webSocket: Uri?,
)

3.0 Json.pretty ->

image

      "RpcDefinition" : {
        "title" : "RpcDefinition",
        "required" : [ "http", "vendor" ],
        "type" : "object",
        "properties" : {
          "vendor" : {
            "title" : "String",
            "type" : "string"
          },
          "http" : {
            "title" : "Uri",
            "type" : "string",
            "format" : "uri"
          },
          "webSocket" : {
            "title" : "Uri#853483442286938760",
            "format" : "uri"
          }
        }
      }

3.1 Json31.pretty ->

image

Note: Disregard the type showing up correctly on the UI for fields formatted as uri. It's inferring the type string from the format. The type does not actually exist within the schema.

      "RpcDefinition" : {
        "properties" : {
          "vendor" : {
            "title" : "String"
          },
          "http" : {
            "format" : "uri",
            "title" : "Uri"
          },
          "webSocket" : {
            "type" : [ "string", "null" ],
            "format" : "uri",
            "title" : "Uri#2887989923754184863"
          }
        },
        "required" : [ "http", "vendor" ],
        "title" : "RpcDefinition"
      }
NecroKote commented 1 month ago

Nice catch! I still think that Json31 should be used since the library promises 3.1 schema, but also there is something fishy going with the schema generation, since the string type is being dropped