Analyzing Types (Reflection)
Type analysis is the first step to generating a schema. The step looks at all involved Kotlin or Java types and extracts information about methods, fields, subtypes, supertypes, type parameters and more.
Using Kotlinx.Serialization
Information about type analysis using Kotlinx.Serialization
Basics
class ExampleClass(
val text: String,
val number: Int?
)../
With the analyzeTypeUsingReflection()
-step, information about a given input type is extracted and resulting
information about the type as well as other referenced types, e.g. "ExampleClass", "String" and "Int" is returned to be used as inputs
for further steps.
The step can be configured to specify which information should be included in the output and in what format.
initial<ExampleClass>().analyzeTypeUsingReflection {
//...
}
Configuration Options
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation 'io.github.smiley4:schema-kenerator-reflection:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-reflection</artifactId>
<version>${version}</version>
</dependency>
Inheritance and Subtypes
Sealed Class and Interfaces
Subtypes of sealed classes and interfaces are detected and included automatically.
sealed class SealedParent {
class ChildOne : SealedParent()
class ChildTwo : SealedParent()
}
initial<SealedParent>().analyzeTypeUsingReflection()
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation 'io.github.smiley4:schema-kenerator-reflection:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-reflection</artifactId>
<version>${version}</version>
</dependency>
Manually Including Subtypes
When using classes that are not "sealed", subtypes are not automatically detected and have to be added as input types for them to be respected in the analysis.
open class ParentManual {
class ChildOne : ParentManual()
class ChildTwo : ParentManual()
}
initial<ParentManual>(
listOf(
typeOf<ParentManual.ChildOne>(),
typeOf<ParentManual.ChildTwo>()
)
)
.analyzeTypeUsingReflection()
.addMissingSupertypeSubtypeRelations()
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-core:$version")
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation 'io.github.smiley4:schema-kenerator-core:$version'
implementation 'io.github.smiley4:schema-kenerator-reflection:$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-reflection</artifactId>
<version>${version}</version>
</dependency>
Core @Subtype-Annotation
Instead of adding the possible subtypes to the input manually, they can be connected automatically using the schema-kenerator-core
@SubType
-annotation.
@SubType(ParentCore.ChildOne::class)
@SubType(ParentCore.ChildTwo::class)
open class ParentCore {
class ChildOne : ParentCore()
class ChildTwo : ParentCore()
}
initial<ParentCore>()
.collectSubTypes()
.analyzeTypeUsingReflection()
.addMissingSupertypeSubtypeRelations()
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-core:$version")
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation 'io.github.smiley4:schema-kenerator-core:$version'
implementation 'io.github.smiley4:schema-kenerator-reflection:$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-reflection</artifactId>
<version>${version}</version>
</dependency>
Jackson @JsonSubTypes-Annotation
Instead of adding the possible subtypes to the input manually, they can also be connected automatically using the Jackson @JsonSubTypes
-annotation.
@JsonSubTypes(
JsonSubTypes.Type(value = ParentJackson.ChildOne::class),
JsonSubTypes.Type(value = ParentJackson.ChildTwo::class),
)
open class ParentJackson {
class ChildOne : ParentJackson()
class ChildTwo : ParentJackson()
}
initial<ParentJackson>()
.collectJacksonSubTypes({
it.analyzeTypeUsingReflection()
})
.analyzeTypeUsingReflection()
.addMissingSupertypeSubtypeRelations()
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation("io.github.smiley4:schema-kenerator-jackson:$version")
implementation 'io.github.smiley4:schema-kenerator-reflection:$version'
implementation 'io.github.smiley4:schema-kenerator-jackson:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-reflection</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-jackson</artifactId>
<version>${version}</version>
</dependency>
Discriminator Properties
A discriminator is used to differentiate between subtypes when (de-)serializing types, i.e. to know which subtype we are dealing with. This property is often times not included as a field in the class itself, but configured e.g. via an annotation. This property can also be added to the type information, e.g. to be later included in generated schemas.
Default Property
sealed class SealedParent {
class ChildOne : SealedParent()
class ChildTwo : SealedParent()
}
initial<SealedParent>()
.analyzeTypeUsingReflection()
.addDiscriminatorProperty("_type")
An "annotation" with name discriminator_marker
is added to the property to mark it and make it possible to find it later, e.g. when generating schemas.
If a property with the name already exists, the maker annotation is added to this property instead.
If a (different) property with marked with the annotation is already present, the step will NOT add the new specified property.
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-core:$version")
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation 'io.github.smiley4:schema-kenerator-core:$version'
implementation 'io.github.smiley4:schema-kenerator-reflection:$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-reflection</artifactId>
<version>${version}</version>
</dependency>
Jackson @JsonTypeInfo-annotation
A discriminator property with a name specified with the Jackson @JsonClassDiscriminator
-annotation can be added to all types that have known subtypes.
Only @JsonTypeInfo#include "PROPERTY" and "EXISTING_PROPERTY" is supported.
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "_type"
)
sealed class ParentDiscriminatorJackson {
class ChildOne : SealedParent()
class ChildTwo : SealedParent()
}
initial<ParentDiscriminatorJackson>()
.analyzeTypeUsingReflection()
.addJacksonTypeInfoDiscriminatorProperty()
An "annotation" with name discriminator_marker
is added to the property to mark it and make it possible to find it later, e.g. when generating schemas.
If a property with the name already exists, the maker annotation is added to this property instead.
If a (different) property with marked with the annotation is already present, the step will NOT add the new specified property.
Required Dependencies
implementation("io.github.smiley4:schema-kenerator-reflection:$version")
implementation("io.github.smiley4:schema-kenerator-jackson:$version")
implementation 'io.github.smiley4:schema-kenerator-reflection:$version'
implementation 'io.github.smiley4:schema-kenerator-jackson:$version'
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-reflection</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>io.github.smiley4</groupId>
<artifactId>schema-kenerator-jackson</artifactId>
<version>${version}</version>
</dependency>