SMILEY4 / ktor-swagger-ui

Kotlin Ktor plugin to generate OpenAPI and provide Swagger UI

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Example of how to document Sealed Classes?

ScottPierce opened this issue · comments

Right now sealed classes returned by the documentation are just {}. Ideally, it would clearly document sealed classes for return types (most important), and also inputs.

Hi, i'm having issues reproducing this problem. Could you provide a minimal example of this behaviour?

This should reproduce it:

    install(SwaggerUI) {
        swagger {
            swaggerUrl = "docs"
            forwardRoot = false
            authentication = "docs"
        }
        info {
            title = "Example API (Experimental)"
            version = "0.1.0"
            description = "This API is private, and is subject to sporadic changes."
        }
        server {
            url = "https://api.example.com"
        }
    }

    routing {
        get("test", {
            response {
                HttpStatusCode.OK to {
                    description = "Successful Request"
                    body<ExampleResponse> {
                    }
                }
            }
        }) {
        }
    }
sealed class ExampleResponse {
    data class A(
        val thisIsA: Boolean
    ) : ExampleResponse()

    data class B(
        val thisIsB: Boolean
    ) : ExampleResponse()
}
image

Similar results if you return a response with the sealed class. The sealed class just shows up as {}.

This is expected behaviour. When serializing ExampleResponse, jackson cannot know what subclasses exist. To let jackson know, add e.g. the following annotation:

@JsonSubTypes(
	JsonSubTypes.Type(value = ExampleResponse.A::class),
	JsonSubTypes.Type(value = ExampleResponse.B::class),
)
sealed class ExampleResponse {
    data class A(
        val thisIsA: Boolean
    ) : ExampleResponse()

    data class B(
        val thisIsB: Boolean
    ) : ExampleResponse()
}

I can't put Jackson Annotations on my models, because they are compiled with Kotlin Multiplatform. :(

the examples could be fixed similar to the kotlinx.dates, but im not sure how to generate the json-schemas in kotlin multiplatform in general. Do you maybe know of any library or way to do that ?
The only other way that i currently know, is to write the json-schema yourself and reference it as a custom-schema (see https://github.com/SMILEY4/ktor-swagger-ui/wiki/Documenting-Routes-(Bodies)#custom-schemas), though i dont know if this manual way is feasible for you.

I think i found a workaround that should work with kotlin multiplatform using this library.

fun main() {
	embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true)
}

private fun Application.myModule() {


	install(SwaggerUI) {
		schemas {
			// overwrite schema builder for specific types with one that supports multiplatform, return null to use default builder
			jsonSchemaBuilder { type ->
				when(type) {
					ExampleResponse::class.java -> toSchema(ExampleResponse.serializer())
					else -> null
				}
			}
		}
	}

	routing {
		get("test", {
			request {
				body<ExampleResponse>()
			}
		}) {
			call.respondText("...")
		}
	}
}

fun toSchema(serializer: SerializationStrategy<*>): String {
	return globalJson.encodeToSchema(serializer, generateDefinitions = false)
}

@Serializable
sealed class ExampleResponse {
	@Serializable
	data class A(
		val thisIsA: Boolean
	) : ExampleResponse()
	@Serializable
	data class B(
		val thisIsB: Boolean
	) : ExampleResponse()
}

Oh interesting. I'll give it a shot. Thanks.

I lost interest in this project, that why there hasn't been any changes for over 2 years if anyone wants to maintain this project or a fork of this project, then I will update this readme

Doesn't bode well for long term use :P

The result is better, but this library is on jcenter (which is deprecated). Does it make sense to pull the code into this codebase?

There's a fork of this project that seems to be a bit more active: https://github.com/tillersystems/json-schema-serialization. Should behave and work almost exactly the same as the other one

Json {
        prettyPrint = true
        encodeDefaults = true
}.encodeToString(ExampleResponse.serializer(), value)

I think it also doesn't use jcenter.

repositories {
    maven(url = "https://raw.githubusercontent.com/glureau/json-schema-serialization/mvn-repo")
}
dependencies {
    implementation("com.github.Ricky12Awesome:json-schema-serialization:0.9.9")
}

It looks like this one when I have a nullble type in my model, it returns a string type in the schema. Also, it seems that the project doesn't allow me to submit an issue :(