diff --git a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/main/kotlin/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationModelConverter.kt b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/main/kotlin/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationModelConverter.kt index 68c779e56..66f176b0c 100644 --- a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/main/kotlin/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationModelConverter.kt +++ b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/main/kotlin/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationModelConverter.kt @@ -5,9 +5,11 @@ import io.swagger.v3.core.converter.ModelConverter import io.swagger.v3.core.converter.ModelConverterContext import io.swagger.v3.core.util.RefUtils import io.swagger.v3.oas.models.media.ArraySchema +import io.swagger.v3.oas.models.media.ComposedSchema import io.swagger.v3.oas.models.media.MapSchema import io.swagger.v3.oas.models.media.ObjectSchema import io.swagger.v3.oas.models.media.Schema +import io.swagger.v3.oas.models.media.StringSchema import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import java.lang.reflect.ParameterizedType @@ -18,6 +20,7 @@ import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.javaType import kotlin.reflect.jvm.jvmErasure +import kotlin.reflect.jvm.jvmName class KotlinxSerializationModelConverter(private val useFqn: Boolean = false) : ModelConverter { @@ -60,12 +63,18 @@ class KotlinxSerializationModelConverter(private val useFqn: Boolean = false) : private fun getPropertySchema(property: KProperty1<*, *>, context: ModelConverterContext): Schema<*> { val propertySchema: Schema<*> - - val name = getPropertyName(property) - + val name = getPropertyName(property) val propertyType = property.returnType.jvmErasure when { + propertyType.sealedSubclasses.isNotEmpty() -> { + propertySchema = ComposedSchema() + propertyType.sealedSubclasses.forEach { subClass -> + val subSchema = resolveRefSchema(subClass.java, context) + propertySchema.addOneOfItem(subSchema) + } + } + propertyType.isSubclassOf(Collection::class) -> { propertySchema = ArraySchema() val value = (property.returnType.javaType as ParameterizedType).actualTypeArguments[0] diff --git a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/java/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationTypeConverterTest.java b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/java/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationTypeConverterTest.java index 86f94962c..237d45abe 100644 --- a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/java/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationTypeConverterTest.java +++ b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/java/io/github/springwolf/addons/kotlinx_serialization_model_converter/converter/KotlinxSerializationTypeConverterTest.java @@ -137,6 +137,28 @@ void testClassWithNestedProperty() { } } + @Nested + class TestSealedClass { + @Test + void testSealedClassSerialization() { + var result = modelConverters.readAll(new AnnotatedType(ClassWithPolymorphism.class)); + assertThat(result).hasSize(3); + assertThat(result.get(Dog.class.getSimpleName())).isNotNull(); + assertThat(result.get(Cat.class.getSimpleName())).isNotNull(); + assertThat(result.get(Pet.class.getSimpleName())).isNull(); + + Schema schema = result.get(ClassWithPolymorphism.class.getSimpleName()); + + final Schema sealedClass = (Schema) schema.getProperties().get("pet"); + assertThat(sealedClass).isNotNull(); + assertThat(sealedClass.getType()).isNull(); + assertThat(sealedClass.get$ref()).isNull(); + assertThat(sealedClass.getOneOf()).hasSize(2); + assertThat(sealedClass.getOneOf().get(0).get$ref()).isEqualTo("#/components/schemas/Cat"); + assertThat(sealedClass.getOneOf().get(1).get$ref()).isEqualTo("#/components/schemas/Dog"); + } + } + @Test void serializeKotlin() { final KotlinxSerializationModelConverter modelConverter = new KotlinxSerializationModelConverter(); diff --git a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/kotlin/io.github.springwolf.addons.kotlinx_serialization_model_converter.converter/SampleEvent.kt b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/kotlin/io.github.springwolf.addons.kotlinx_serialization_model_converter.converter/SampleEvent.kt index 181c734b6..7d48d1dc9 100644 --- a/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/kotlin/io.github.springwolf.addons.kotlinx_serialization_model_converter.converter/SampleEvent.kt +++ b/springwolf-add-ons/springwolf-kotlinx-serialization-model-converter/src/test/kotlin/io.github.springwolf.addons.kotlinx_serialization_model_converter.converter/SampleEvent.kt @@ -1,5 +1,6 @@ package io.github.springwolf.addons.kotlinx_serialization_model_converter.converter +import io.github.springwolf.addons.kotlinx_serialization_model_converter.converter.ClassWithNestedProperty.NestedClass import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import java.time.LocalDate @@ -89,4 +90,22 @@ data class ClassWithNestedProperty( val name: String, val color: Color, ) -} \ No newline at end of file +} + +@Serializable +data class ClassWithPolymorphism( + @SerialName("pet") + val pet: Pet, +) + + +@Serializable +sealed interface Pet + +@Serializable +@SerialName("dog") +data class Dog(val bark: Boolean, val breed: String) : Pet + +@Serializable +@SerialName("cat") +data class Cat(val hunt: Boolean, val age: Int): Pet \ No newline at end of file