Closed ScottPierce closed 1 year ago
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()
}
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 :(
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.