Skip to content

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
Resulting Root Schema:
{
  "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
Resulting Root Schema:
{
  "type" : "object",
  "required" : [ "nested", "number" ],
  "properties" : {
    "nested" : {
      "$ref" : "#/components/schemas/examples.NestedClass"
    },
    "number" : {
      "type" : "integer",
      "format" : "int32"
    },
    "text" : {
      "type" : [ "null", "string" ]
    }
  },
}
Referenced Schema (e.g. .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
Resulting Root Schema:
{
   "$ref": "#/components/schemas/examples.ExampleClass
}
Referenced Schema (e.g. .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

API Reference for generateSwaggerSchema

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>