major: v4 alpha (#505)
This commit is contained in:
@ -1,20 +1,51 @@
|
||||
package io.bkbn.kompendium.json.schema
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.EnumDefinition
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.hasAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
|
||||
class KotlinXSchemaConfigurator : SchemaConfigurator {
|
||||
|
||||
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> =
|
||||
clazz.memberProperties
|
||||
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> {
|
||||
return clazz.memberProperties
|
||||
.filterNot { it.hasAnnotation<Transient>() }
|
||||
.filter { clazz.primaryConstructor?.parameters?.map { it.name }?.contains(it.name) ?: true }
|
||||
}
|
||||
|
||||
override fun serializableName(property: KProperty1<out Any, *>): String =
|
||||
property.annotations
|
||||
.filterIsInstance<SerialName>()
|
||||
.firstOrNull()?.value ?: property.name
|
||||
|
||||
override fun sealedTypeEnrichment(
|
||||
implementationType: KType,
|
||||
implementationSchema: JsonSchema,
|
||||
): JsonSchema {
|
||||
return if (implementationSchema is TypeDefinition && implementationSchema.type == "object") {
|
||||
implementationSchema.copy(
|
||||
required = implementationSchema.required?.plus("type"),
|
||||
properties = implementationSchema.properties?.plus(
|
||||
mapOf(
|
||||
"type" to EnumDefinition("string", enum = setOf(determineTypeQualifier(implementationType)))
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
implementationSchema
|
||||
}
|
||||
}
|
||||
|
||||
private fun determineTypeQualifier(type: KType): String {
|
||||
val nameOverrideAnnotation = (type.classifier as KClass<*>).findAnnotation<SerialName>()
|
||||
return nameOverrideAnnotation?.value ?: (type.classifier as KClass<*>).qualifiedName!!
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
package io.bkbn.kompendium.json.schema
|
||||
|
||||
import io.bkbn.kompendium.json.schema.definition.JsonSchema
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.KType
|
||||
|
||||
interface SchemaConfigurator {
|
||||
fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>>
|
||||
fun serializableName(property: KProperty1<out Any, *>): String
|
||||
|
||||
open class Default : SchemaConfigurator {
|
||||
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> =
|
||||
clazz.memberProperties
|
||||
|
||||
override fun serializableName(property: KProperty1<out Any, *>): String = property.name
|
||||
}
|
||||
fun sealedTypeEnrichment(
|
||||
implementationType: KType,
|
||||
implementationSchema: JsonSchema
|
||||
): JsonSchema
|
||||
}
|
||||
|
@ -25,15 +25,18 @@ object SealedObjectHandler {
|
||||
val subclasses = clazz.sealedSubclasses
|
||||
.map { it.createType(type.arguments) }
|
||||
.map { t ->
|
||||
SchemaGenerator.fromTypeToSchema(t, cache, schemaConfigurator, enrichment).let { js ->
|
||||
if (js is TypeDefinition && js.type == "object") {
|
||||
val slug = t.getSlug(enrichment)
|
||||
cache[slug] = js
|
||||
ReferenceDefinition(t.getReferenceSlug(enrichment))
|
||||
} else {
|
||||
js
|
||||
SchemaGenerator.fromTypeToSchema(t, cache, schemaConfigurator, enrichment)
|
||||
.let {
|
||||
schemaConfigurator.sealedTypeEnrichment(t, it)
|
||||
}.let { js ->
|
||||
if (js is TypeDefinition && js.type == "object") {
|
||||
val slug = t.getSlug(enrichment)
|
||||
cache[slug] = js
|
||||
ReferenceDefinition(t.getReferenceSlug(enrichment))
|
||||
} else {
|
||||
js
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.toSet()
|
||||
return AnyOfDefinition(subclasses)
|
||||
|
@ -13,7 +13,7 @@ object Helpers {
|
||||
fun KType.getSlug(enrichment: Enrichment? = null) = when (enrichment) {
|
||||
is TypeEnrichment<*> -> getEnrichedSlug(enrichment)
|
||||
is PropertyEnrichment -> error("Slugs should not be generated for field enrichments")
|
||||
null -> getSimpleSlug()
|
||||
else -> getSimpleSlug()
|
||||
}
|
||||
|
||||
fun KType.getSimpleSlug(): String = when {
|
||||
@ -26,7 +26,7 @@ object Helpers {
|
||||
fun KType.getReferenceSlug(enrichment: Enrichment? = null): String = when (enrichment) {
|
||||
is TypeEnrichment<*> -> getSimpleReferenceSlug() + "-${enrichment.id}"
|
||||
is PropertyEnrichment -> error("Reference slugs should never be generated for field enrichments")
|
||||
null -> getSimpleReferenceSlug()
|
||||
else -> getSimpleReferenceSlug()
|
||||
}
|
||||
|
||||
private fun KType.getSimpleReferenceSlug() = when {
|
||||
|
Reference in New Issue
Block a user