Schemas
An example showing different ways to handle schemas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 | package io.github.smiley4.ktoropenapi.examples
import com.fasterxml.jackson.annotation.JsonSubTypes
import io.github.smiley4.ktoropenapi.OpenApi
import io.github.smiley4.ktoropenapi.config.SchemaGenerator
import io.github.smiley4.ktoropenapi.config.descriptors.anyOf
import io.github.smiley4.ktoropenapi.config.descriptors.array
import io.github.smiley4.ktoropenapi.config.descriptors.ref
import io.github.smiley4.ktoropenapi.get
import io.github.smiley4.ktoropenapi.openApi
import io.github.smiley4.ktorredoc.redoc
import io.github.smiley4.ktorswaggerui.swaggerUI
import io.ktor.server.application.Application
import io.ktor.server.application.install
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.server.response.respondText
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import io.swagger.v3.oas.models.media.Schema
import java.time.LocalDateTime
fun main() {
embeddedServer(Netty, port = 8080, host = "localhost", module = Application::myModule).start(wait = true)
}
private fun Application.myModule() {
// Install and customize the OpenApi Plugin
install(OpenApi) {
schemas {
// add a swagger schema to the component section of the api spec with the id "swagger-schema"
schema("swagger-schema", Schema<Any>().also {
it.type = "number"
it.title = "Custom Type"
})
// add a type to the component section of the api spec with the id "type-schema"
schema<MySchemaClass>("type-schema")
// customized schema generation
generator = SchemaGenerator.reflection {
// overwrite default schema generation with one specific for LocalDateTime that correctly handles "type" and "format"
overwrite(SchemaGenerator.TypeOverwrites.LocalDateTime())
}
}
}
routing {
// add the routes for the api spec, swagger-ui and redoc
route("swagger") {
swaggerUI("/api.json")
}
route("api.json") {
openApi()
}
route("redoc") {
redoc("/api.json")
}
get("basic", {
request {
// directly specify the schema type
body<MySchemaClass>()
}
}) {
call.respondText("...")
}
get("global-swagger-schema", {
request {
// reference and use the schema from the component section with the id "swagger-schema"
body(ref("swagger-schema"))
}
}) {
call.respondText("...")
}
get("global-type-schema", {
request {
// reference and use the schema from the component section with the id "type-schema"
body(ref("type-schema"))
}
}) {
call.respondText("...")
}
get("array-schema", {
request {
// an array of items with the referenced schema with the id "type-schema"
body(
array(
ref("type-schema")
)
)
}
}) {
call.respondText("...")
}
get("anyof-schema", {
request {
// either the referenced schema with id "type-schema" or "swagger-schema"
body(
anyOf(
ref("type-schema"),
ref("swagger-schema")
)
)
}
}) {
call.respondText("...")
}
get("type-overwrite", {
request {
// schema is not generated the normal way but the overwriting schema from the config is used instead
body<LocalDateTime>()
}
}) {
call.respondText("...")
}
get("jackson-subtypes", {
request {
// jackson subtypes are detected automatically
body<BaseType>()
}
}) {
call.respondText("...")
}
}
}
private data class MySchemaClass(
val someValue: String
)
@JsonSubTypes(
JsonSubTypes.Type(value = SubTypeA::class),
JsonSubTypes.Type(value = SubTypeB::class),
)
private open class BaseType(val base: String)
private class SubTypeA(base: String, val a: Int) : BaseType(base)
private class SubTypeB(base: String, val b: Boolean) : BaseType(base)
|