Skip to content

Examples

An example showing different ways to handle examples.

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

import io.github.smiley4.ktoropenapi.OpenApi
import io.github.smiley4.ktoropenapi.config.descriptors.KTypeDescriptor
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 kotlin.reflect.typeOf

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) {
        examples {

            // specify two shared examples
            example("Shared A") {
                description = "first shared example"
                value = MyExampleClass(
                    someValue = "shared a"
                )
            }
            example("Shared B") {
                description = "second shared example"
                value = MyExampleClass(
                    someValue = "shared b"
                )
            }

            // encoder used in "custom-encoder" example
            encoder { type, example ->
                // encode just the wrapped value for CustomEncoderData class
                if (type is KTypeDescriptor && type.type == typeOf<CustomEncoderData>())
                    (example as CustomEncoderData).number
                // return the example unmodified to fall back to default encoder
                else
                    example
            }
        }
    }

    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")
        }


        get("basic", {
            request {
                body<MyExampleClass> {
                    // specify two example values
                    example("Example 1") {
                            description = "A first example value"
                            value = MyExampleClass(
                                someValue = "example 1"
                            )
                    }
                    example("Example 2") {
                        description = "A second example value"
                        value = MyExampleClass(
                            someValue = "example 2"
                        )
                    }
                }
            }
        }) {
            call.respondText("...")
        }


        get("reference-shared", {
            request {
                body<MyExampleClass> {
                    // reference two shared examples specified in the plugin config (and placed in the component section)
                    exampleRef("Example 1", "Shared A")
                    exampleRef("Example 2", "Shared B")
                }
            }
        }) {
            call.respondText("...")
        }

        get("custom-encoder", {
            request {
                body<CustomEncoderData> {
                    // The type is CustomEncoderData, but it's actually encoded as a plain number
                    // See configuration for encoder
                    example("Example 1") {
                        value = CustomEncoderData(123)
                    }
                }
            }
        }) {
            call.respondText("...")
        }
    }

}


private data class MyExampleClass(
    val someValue: String
)

private data class CustomEncoderData(
    val number: Int
)