Skip to content

Schema Generation

Example showcasing possible configurations for customizing the automatic schema generation.

 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
package io.github.smiley4.ktoropenapi.examples

import io.github.smiley4.ktoropenapi.OpenApi
import io.github.smiley4.ktoropenapi.config.SchemaGenerator
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.github.smiley4.schemakenerator.serialization.SerializationSteps.analyzeTypeUsingKotlinxSerialization
import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.RequiredHandling
import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.compileReferencingRoot
import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.generateSwaggerSchema
import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.withTitle
import io.github.smiley4.schemakenerator.swagger.data.TitleType
import io.ktor.http.HttpStatusCode
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.respond
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import kotlinx.serialization.Serializable

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

private fun Application.myModule() {

    // Install and configure the OpenApi plugin
    install(OpenApi) {
        schemas {
            // replace default schema-generator with configurable pre-defined generator, or ...
            generator = SchemaGenerator.kotlinx {
                nullables = RequiredHandling.NON_REQUIRED
                optionals = RequiredHandling.REQUIRED
                title = TitleType.SIMPLE
                explicitNullTypes = false
            }
            // ... replace default schema-generator with completely custom generator
            generator = { type ->
                type
                    .analyzeTypeUsingKotlinxSerialization()
                    .generateSwaggerSchema {
                        nullables = RequiredHandling.NON_REQUIRED
                        optionals = RequiredHandling.REQUIRED
                    }
                    .withTitle(TitleType.SIMPLE)
                    .compileReferencingRoot(
                        explicitNullTypes = false
                    )
            }
        }
    }

    routing {

        // add the routes for  the OpenAPI spec, Swagger UI and ReDoc
        route("swagger") {
            swaggerUI("/api.json")
        }
        route("api.json") {
            openApi()
        }
        route("redoc") {
            redoc("/api.json")
        }

        // a documented route
        get("hello", {
            // information about the request
            response {
                // information about a "200 OK" response
                code(HttpStatusCode.OK) {
                    // body of the response
                    body<MyResponseBody>()
                }
            }
        }) {
            call.respond(HttpStatusCode.NotImplemented, "...")
        }

    }

}

@Serializable
private class MyResponseBody(
    val name: String,
)