Generating Swagger Schema
Basics
After analyzing a type, extracting and modifying data, the swagger schema is created with two main steps:
1. generateSwaggerSchema
: generates an independent swagger schema for each processed type. At this stage, the schemas may not be 100% valid JSON schemas.
2. compile[...]
: this step takes the independent swagger schemas created by the generateSwaggerSchema
-step and merges them into one or multiple final valid schemas
class ExampleClass(
val nested: NestedClass,
val number: Int,
val text: String?,
)
class NestedClass(
val flag: Boolean
)
compileInlining()
takes the independent swagger Schemas generated by generateSwaggerSchema
and creates a single schema by simply inlining all referenced schemas.
initial<ExampleClass>()
.analyzeTypeUsingReflection()
.generateSwaggerSchema()
.compileInlining()
.swagger
{
"type" : "object",
"required" : [ "nested", "number" ],
"properties" : {
"nested" : {
"type" : "object",
"required" : [ "flag" ],
"properties" : {
"flag" : {
"type" : "boolean"
}
},
},
"number" : {
"type" : "integer",
"format" : "int32"
},
"text" : {
"type" : [ "null", "string" ]
}
}
}
compileReferencing()
takes the independent swagger Schemas generated by generateSwaggerSchema
and only references them. Very simple schemas like primitives are still inlined.
Referenced schemas are returned in an extra property .compileReferencing().componentSchemas
.
initial<ExampleClass>()
.analyzeTypeUsingReflection()
.generateSwaggerSchema()
.compileReferencing()
.swagger
{
"type" : "object",
"required" : [ "nested", "number" ],
"properties" : {
"nested" : {
"$ref" : "#/components/schemas/examples.NestedClass"
},
"number" : {
"type" : "integer",
"format" : "int32"
},
"text" : {
"type" : [ "null", "string" ]
}
},
}
.compileReferencing().componentSchemas["examples.NestedClass"]
):
{
"type" : "object",
"required" : [ "flag" ],
"properties" : {
"flag" : {
"type" : "boolean"
}
}
}
compileReferencingRoot()
behaves the same as compileReferencing()
, but also references the root schema.
Referenced schemas are returned in an extra property .compileReferencing().componentSchemas
.
initial<ExampleClass>()
.analyzeTypeUsingReflection()
.generateSwaggerSchema()
.compileReferencingRoot()
.json
{
"$ref": "#/components/schemas/examples.ExampleClass
}
.compileReferencingRoot().componentSchemas["examples.ExampleClass"]
):
{
"type" : "object",
"required" : [ "nested", "number" ],
"properties" : {
"nested" : {
"$ref" : "#/components/schemas/examples.NestedClass"
},
"number" : {
"type" : "integer",
"format" : "int32"
},
"text" : {
"type" : [ "null", "string" ]
}
}
}
Configuration Options
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>
Reference Path Type
Schemas can be referenced using different paths or "ids" when using compileReferencing
or compileReferencingRoot
RefType.OPENAPI_FULL
: uses the full qualified version of the type names valid for OpenAPI specifications, e.g.some.examples.MyClass_kotlin.Int
RefType.OPENAPI_SIMPLE
: uses a shorter simple version of the type names valid for OpenAPI specifications, e.g.MyClass_Int
RefType.FULL
: uses the full qualified version of the type names, e.g.some.examples.MyClass<kotlin.Int>
RefType.SIMPLE
: uses a shorter simple version of the type names, e.g.MyClass<Int>
Simple OpenAPI Path Type
initial<List<GenericClass<String>>>()
.analyzeTypeUsingReflection()
.generateJsonSchema()
.compileReferencing(pathType = RefType.OPENAPI_SIMPLE)
{
"type": "array",
"items": {
"$ref": "#/definitions/GenericClass_String"
}
}
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>
Automatically Adding Titles
A "title" property can be automatically added to all types in the schema.
initial<List<GenericClass<String>>>()
.analyzeTypeUsingReflection()
.generateSwaggerSchema()
.withTitle(type = TitleType.SIMPLE)
.compileInlining()
{
"title": "List_GenericClass_String",
"type": "array",
"items": {
"title": "GenericClass_String",
"type": "object",
"required": [ "value" ],
"properties": {
"value": {
"title": "String",
"type": "string"
}
}
}
}
The type of the title can be configured:
TitleType.OPENAPI_FULL
: uses the full qualified version of the type names valid for OpenAPI specifications, e.g.some.examples.MyClass_kotlin.Int
TitleType.OPENAPI_SIMPLE
: uses a shorter simple version of the type names valid for OpenAPI specifications, e.g.MyClass_Int
TitleType.FULL
: uses the full qualified version of the type names, e.g.some.examples.MyClass<kotlin.Int>
TitleType.SIMPLE
: uses a shorter simple version of the type names, e.g.MyClass<Int>
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>
Schema-Kenerator Annotations
Additional properties of the swagger schema can be filled with extra information from annotations, e.g. descriptions or default values. The handleCoreAnnotations()
-step adds information from annotations from schema-kenerator-core
to the schemas.
@Title("Annotated Class")
@Description("some description")
@Default("default value")
@Example("example 1")
@Deprecated
class CoreAnnotatedClass(
@Description("String field description")
@Default("A default String value")
@Example("An example of a String value")
val stringValue: String,
@Description("Int field description")
@Default("1111")
@Example("2222")
val intValue: Int,
)
initial<CoreAnnotatedClass>()
.analyzeTypeUsingReflection()
.generateSwaggerSchema()
.handleCoreAnnotations()
.compileInlining()
{
"title" : "Annotated Class",
"type" : "object",
"description" : "some description",
"example" : "example 1",
"deprecated" : true,
"default" : "default value",
"required" : [ "intValue", "stringValue" ],
"properties" : {
"stringValue" : {
"type" : "string",
"description" : "String field description",
"example" : "An example of a String value",
"default" : "A default String value"
},
"intValue" : {
"type" : "integer",
"description" : "Int field description",
"format" : "int32",
"example" : "2222",
"default" : "1111"
}
}
}
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-core:$version")
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-core:$version'
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-core</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>
Jackson Annotations
Additional properties of the swagger schema can be filled with extra information from annotations, e.g. descriptions or default values. The handleJacksonSwaggerAnnotations()
-step adds information from Jackson annotations to the schemas.
class JacksonAnnotatedClass(
@JsonPropertyDescription("Example description of the field")
val value: String
)
initial<JacksonAnnotatedClass>()
.analyzeTypeUsingReflection()
.generateJsonSchema()
.handleJacksonSwaggerAnnotations()
.compileInlining()
{
"type" : "object",
"required" : [ "value" ],
"properties" : {
"value" : {
"type" : "string",
"description" : "Example description of the field"
}
}
}
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-jackson-swagger:$version")
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-jackson-swagger:$version'
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-jackson-swagger</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>
Swagger Annotations
Additional properties of the swagger schema can be filled with extra information from annotations, e.g. descriptions or default values. The handleSchemaAnnotations()
-step adds information from Swagger Core @Schema
and @ArraySchema
annotations to the schemas.
@Schema(
title = "Swagger Annotated Class",
name = "SwaggerAnnotatedClass",
description = "some description",
)
private class SwaggerAnnotatedClass(
@Schema(
description = "some value",
title = "Some Value",
name = "someValue",
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
allowableValues = ["1", "2", "3", "4"],
defaultValue = "1",
accessMode = Schema.AccessMode.READ_ONLY,
minLength = 1,
maxLength = 10,
format = "single-digit",
minimum = "0",
maximum = "9",
exclusiveMaximum = true
)
val myValue: Int,
@ArraySchema(
minItems = 0,
maxItems = 10,
uniqueItems = true
)
val someTags: List<String>
)
initial<JacksonAnnotatedClass>()
.analyzeTypeUsingReflection()
.generateJsonSchema()
.handleSchemaAnnotations()
.compileInlining()
{
"title" : "Swagger Annotated Class",
"description" : "some description",
"type" : "object",
"required" : [ "myValue", "someTags" ],
"properties" : {
"myValue" : {
"title" : "Some Value",
"maximum" : 9,
"exclusiveMaximum" : true,
"minimum" : 0,
"exclusiveMinimum" : false,
"maxLength" : 10,
"minLength" : 1,
"type" : "integer",
"description" : "some value",
"format" : "single-digit",
"readOnly" : true,
"enum" : [ "1", "2", "3", "4" ],
"default" : "1"
},
"someTags" : {
"maxItems" : 10,
"minItems" : 0,
"uniqueItems" : true,
"type" : "array",
"items" : {
"type" : "string"
}
}
}
}
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-swagger:$version")
implementation 'io.github.smiley4:schema-kenerator-swagger:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-swagger</artifactId>
<version>${version}</version>
</dependency>