Open outlndrr opened 1 month ago
Hi @outlndrr i'm having issues reproducing your described problem. The setup
install(SwaggerUI) {
schemas {
overwrite<LocalDateTime>( // overwrite LocalDateTime
Schema<String>().also {
it.type = "string"
it.format = "date-time" // with format
}
)
}
}
routing {
route("swagger") { swaggerUI("/api.json") }
route("api.json") { openApiSpec() }
get("test", {
request {
body<LocalDateTime>() // use LocalDateTime as request body
}
}) {}
}
produces
"requestBody" : {
"content" : {
"text/plain" : {
"schema" : {
"type" : "string",
"format" : "date-time" <- includes format
}
}
},
"required" : false
},
Are you using LocalDateTime as the type of a fields of another type (e.g. class SomeResponseData(val date: LocalDateTime)
) ? In this case overwrite
in the swagger plugin-config will not work, since it only applies to "root" types.
For applying custom schemas to all types (including nested ones), the schema-generator has to be customized directly. See https://github.com/SMILEY4/ktor-swagger-ui/wiki/Customizing-Schema-Generation and https://github.com/SMILEY4/schema-kenerator/wiki/Type-Redirects for more information.
Hi @SMILEY4
Can you please provide example how to redirect LocalDateTime
into the string with the specific format? The example in "Type Redirects" is not very helpful for my situation.
Ah sorry, i think i missed something here.
There are ~two options to properly customize the resulting schema of a type
redirects which allow you to "replace" a type with another given type for schema generation. So you could e.g. redirect "LocalDateTime" to "String" and have all occurences of "LocalDateTime" be generated as a schema for string. Though this does not allow you to easily add the "format" property, since this only affects the "input data" for the schema generation, not how to generate the schema itself.
custom processors which allow you to completly customize the raw input data for the schema generator (same data as extracted from classes via reflection or kotlinx), though the same problem as with redirects exists here.
There is one possible (maybe slightly hacky) workaround though:
val result = typeOf<ClassWithLocalDateTime>()
.processKotlinxSerialization {
// REGISTER A CUSTOM PROCESSOR FOR 'LocalDateTime' HERE (works the same when using 'processReflection')
customProcessor<LocalDateTime> {
PrimitiveTypeData( // build a custom type for the generation of the localdatetime-schema based on String
id = TypeId.build(String::class.qualifiedName!!),
simpleName = String::class.simpleName!!,
qualifiedName = String::class.qualifiedName!!,
annotations = mutableListOf(
AnnotationData( // add a custom annotation to the type that tells a schema-generation step to set the "format" property
name = "swagger-format",
values = mutableMapOf("format" to "date-time"),
annotation = null
)
)
)
}
}
.generateSwaggerSchema()
// ADD A STEP TO CUSTOMIZE THE GENERATED SWAGGER_SCHEMA
.let { bundle ->
val typeDataMap = bundle.buildTypeDataMap()
bundle.also { schema ->
process(schema.data, typeDataMap) // check the root schema
schema.supporting.forEach { process(it, typeDataMap) } // check additional schemas
}
}
.compileInlining()
fun process(schema: SwaggerSchema, typeDataMap: Map<TypeId, BaseTypeData>) {
schema.typeData.annotations
.find { it.name == "swagger-format" } // find our custom annotation
?.also { annotation ->
schema.swagger.format = annotation.values["format"] as String // set the "format"-property of the swagger-schema
}
}
println(json.writeValueAsString(result.swagger))
result.componentSchemas.forEach { (name, schema) ->
println("$name: ${json.writeValueAsString(schema)}")
}
Adding the custom processor and the extra step to the pipeline should produce the correct schema, though you might have to adapt the surrounding configuration a bit for your use case. I'll try to make this whole thing a bit more convenient with the next version.
If you try this, please let me know it it worked for you and if you encounter any more questions or issues :)
I have overwrite block inside Swagger plugin:
But it doesn't apply the format if it's the body of the request and displays as a common string:
Is it possible to apply overwriting to the body as well?
Library version: 3.0.0