Skip to content

Manual Schema Definition

Schemas can be defined manually using OpenAPI schema objects, providing complete control over the schema structure. This approach is useful when automatic schema generation doesn't produce the desired result.

Manual schemas use the io.swagger.v3.oas.models.media.Schema class from the Swagger library. This class provides all properties defined in the OpenAPI specification, allowing schemas to be built exactly as they should appear in the final specification.

import io.swagger.v3.oas.models.media.Schema

post("data", {
    request {
        body(Schema<Any>().apply {
            type = "object"
            title = "CustomData"
            properties = mapOf(
                "id" to Schema<Any>().apply {
                    type = "string"
                    format = "uuid"
                },
                "value" to Schema<Any>().apply {
                    type = "number"
                    minimum = BigDecimal.ZERO
                    maximum = BigDecimal(100)
                }
            )
            required = listOf("id", "value")
        })
    }
}) { }

This creates a schema with two properties: a UUID-formatted string id and a numeric value constrained between 0 and 100.

Composite Schemas

Composite schemas combine multiple schemas using logical operators. This can also include combining global schemas defined in the plugin configuration.

install(OpenApi) {
    schemas {
        schema<User>("user")
    }
}

get("users", {
    description = "Retrieves all users"
    response {
        code(HttpStatusCode.OK) {
            body(
                array(
                    anyOf(
                        ref("type-schema"),
                        type<Admin>()
                    )
                )
            )
        }
    }
}) { }

anyOf

The anyOf operator indicates that a value can match any one of the provided schemas:

import io.github.smiley4.ktoropenapi.config.anyOf

body(anyOf(
    Schema<Any>().apply {
        type = "string"
        format = "email"
    },
    Schema<Any>().apply {
        type = "string"
        format = "uri"
    }
)) { }

This accepts either an email address or a URI. The value must be valid according to at least one of the schemas.

array

Composite schemas can be used as array items:

import io.github.smiley4.ktoropenapi.config.array

body(
    array(
        ref("user-schema")
    )
) { }

type

This can be used to use schemas automatically generated from a given Kotlin type with other operations:

import io.github.smiley4.ktoropenapi.config.type

body(
    array(
        type<User>(),
    )
) { }

ref

This can be used to use globally defined schemas with other operations:

import io.github.smiley4.ktoropenapi.config.ref

body(
    array(
        ref("product"),
    )
) { }

empty

The empty function is a shortcut to create an empty schema:

import io.github.smiley4.ktoropenapi.config.empty

body(
    anyOf(
        type<SuccessResponse>(),
        empty()
    )
) { }