CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-jvm

Kotlin multiplatform serialization runtime library core module with JVM target support

Pending
Overview
Eval results
Files

descriptors.mddocs/

Descriptors

The descriptor system in kotlinx.serialization provides structural metadata about serializable types. Descriptors describe the shape, names, and characteristics of serialized data, enabling format implementations to understand how to encode and decode objects without needing to know the actual Kotlin types.

Capabilities

Core Descriptor Interface

The fundamental interface that describes the structure of any serializable type.

/**
 * Describes the structure of a serializable type including its name, kind, and elements.
 * Used by encoders and decoders to understand the shape of data they're processing.
 */
interface SerialDescriptor {
    /** The serial name of the described type */
    val serialName: String
    
    /** The kind of serial data (primitive, structured, etc.) */
    val kind: SerialKind
    
    /** Number of elements in this descriptor */
    val elementsCount: Int
    
    /** Annotations present on the described type */
    val annotations: List<Annotation>
    
    /** Whether this descriptor represents an inline value class */
    val isInline: Boolean
    
    /** Whether this descriptor is nullable */  
    val isNullable: Boolean
    
    /** Get the name of element at specified index */
    fun getElementName(index: Int): String
    
    /** Get the index of element with specified name */
    fun getElementIndex(name: String): Int
    
    /** Get annotations for element at specified index */
    fun getElementAnnotations(index: Int): List<Annotation>
    
    /** Get descriptor for element at specified index */
    fun getElementDescriptor(index: Int): SerialDescriptor
    
    /** Check if element at specified index is optional */
    fun isElementOptional(index: Int): Boolean
}

Usage Examples:

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*

@Serializable
data class User(val name: String, val age: Int, val email: String? = null)

val descriptor = User.serializer().descriptor

println(descriptor.serialName)      // "User"
println(descriptor.kind)            // StructureKind.CLASS  
println(descriptor.elementsCount)   // 3

// Inspect elements
for (i in 0 until descriptor.elementsCount) {
    println("${descriptor.getElementName(i)}: ${descriptor.isElementOptional(i)}")
}
// name: false
// age: false  
// email: true

Serial Kinds

Type hierarchy that categorizes different kinds of serializable data structures.

/**
 * Base sealed class for all serial kinds that categorize serializable types.
 */
sealed class SerialKind

/**
 * Kinds for primitive values that can be directly encoded/decoded.
 */
sealed class PrimitiveKind : SerialKind() {
    object BOOLEAN : PrimitiveKind()
    object BYTE : PrimitiveKind()
    object CHAR : PrimitiveKind()
    object SHORT : PrimitiveKind()
    object INT : PrimitiveKind()
    object LONG : PrimitiveKind()
    object FLOAT : PrimitiveKind()
    object DOUBLE : PrimitiveKind()  
    object STRING : PrimitiveKind()
}

/**
 * Kinds for structured values that contain multiple elements.
 */
sealed class StructureKind : SerialKind() {
    /** Regular class with named properties */
    object CLASS : StructureKind()
    
    /** Ordered collection of elements */
    object LIST : StructureKind()
    
    /** Key-value mapping */
    object MAP : StructureKind()
    
    /** Object instance (singleton) */
    object OBJECT : StructureKind()
}

/**
 * Kinds for polymorphic types that can have multiple runtime implementations.
 */
sealed class PolymorphicKind : SerialKind() {
    /** Sealed class hierarchy with known subclasses */
    object SEALED : PolymorphicKind()
    
    /** Open class/interface with potentially unknown subclasses */
    object OPEN : PolymorphicKind()
}

/**
 * Special kinds for specific serialization scenarios.
 */
object SerialKind {
    /** Type that requires contextual serializer lookup */
    object CONTEXTUAL : SerialKind()
    
    /** Enum type */
    object ENUM : SerialKind()
}

Descriptor Factory Functions

Factory functions for creating descriptors programmatically.

/**
 * Creates a primitive descriptor for basic types.
 * @param serialName The name of the described type
 * @param kind The primitive kind
 * @return SerialDescriptor for the primitive type
 */
fun PrimitiveSerialDescriptor(serialName: String, kind: PrimitiveKind): SerialDescriptor

/**
 * DSL builder for creating class descriptors with elements.
 * @param serialName The name of the described type
 * @param builderAction Lambda to configure descriptor elements
 * @return SerialDescriptor for the class
 */
fun buildClassSerialDescriptor(
    serialName: String,
    builderAction: ClassSerialDescriptorBuilder.() -> Unit = {}
): SerialDescriptor

/**
 * Creates a descriptor identical to original but with different name.
 * @param serialName The new name for the descriptor
 * @param original The original descriptor to copy
 * @return SerialDescriptor with new name
 */
fun SerialDescriptor(serialName: String, original: SerialDescriptor): SerialDescriptor

/**
 * Builder class for constructing class descriptors.
 */
class ClassSerialDescriptorBuilder {
    /** Add an element to the descriptor */
    fun element(
        elementName: String,
        descriptor: SerialDescriptor,
        annotations: List<Annotation> = emptyList(),
        isOptional: Boolean = false
    )
    
    /** Add annotations to the descriptor itself */  
    fun annotations(annotations: List<Annotation>)
}

Usage Examples:

import kotlinx.serialization.descriptors.*

// Create primitive descriptor
val stringDescriptor = PrimitiveSerialDescriptor("MyString", PrimitiveKind.STRING)

// Create class descriptor with DSL
val personDescriptor = buildClassSerialDescriptor("Person") {
    element("name", PrimitiveSerialDescriptor("kotlin.String", PrimitiveKind.STRING))
    element("age", PrimitiveSerialDescriptor("kotlin.Int", PrimitiveKind.INT))
    element("email", PrimitiveSerialDescriptor("kotlin.String", PrimitiveKind.STRING), isOptional = true)
}

// Copy descriptor with new name
val aliasDescriptor = SerialDescriptor("PersonAlias", personDescriptor)

Collection Descriptor Functions

Specialized functions for creating descriptors for collection types.

/**
 * Creates a descriptor for List<T> structures.
 * @param elementDescriptor Descriptor for list elements
 * @return SerialDescriptor for List type
 */
fun listSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor

/**
 * Creates a descriptor for Set<T> structures.
 * @param elementDescriptor Descriptor for set elements  
 * @return SerialDescriptor for Set type
 */
fun setSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor

/**
 * Creates a descriptor for Map<K,V> structures.
 * @param keyDescriptor Descriptor for map keys
 * @param valueDescriptor Descriptor for map values
 * @return SerialDescriptor for Map type
 */
fun mapSerialDescriptor(
    keyDescriptor: SerialDescriptor, 
    valueDescriptor: SerialDescriptor
): SerialDescriptor

Descriptor Lookup Functions

Functions for obtaining descriptors at runtime.

/**
 * Retrieves a descriptor for the given reified type T.
 * @return SerialDescriptor for type T
 */
inline fun <reified T> serialDescriptor(): SerialDescriptor

/**
 * Retrieves a descriptor for the given KType.
 * @param type The KType to get descriptor for
 * @return SerialDescriptor for the specified type
 */
fun serialDescriptor(type: KType): SerialDescriptor

Usage Examples:

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlin.reflect.typeOf

@Serializable
data class Product(val name: String, val price: Double)

// Get descriptor for known type
val productDescriptor = serialDescriptor<Product>()

// Get descriptor for collection types
val listDescriptor = serialDescriptor<List<Product>>() 
val mapDescriptor = serialDescriptor<Map<String, Product>>()

// Runtime descriptor lookup
val typeDescriptor = serialDescriptor(typeOf<List<String>>())

// Create collection descriptors manually
val customListDesc = listSerialDescriptor(PrimitiveSerialDescriptor("kotlin.String", PrimitiveKind.STRING))
val customMapDesc = mapSerialDescriptor(
    PrimitiveSerialDescriptor("kotlin.String", PrimitiveKind.STRING),
    serialDescriptor<Product>()
)

Descriptor Extension Properties

Additional properties available on descriptors for advanced use cases.

/**
 * Extension property that returns the captured KClass for the descriptor.
 * Useful for runtime type checking and reflection operations.
 */
val SerialDescriptor.capturedKClass: KClass<Any>?

Usage Patterns

Custom Serializer Descriptors

When implementing custom serializers, you typically need to provide appropriate descriptors:

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*

object LocalDateSerializer : KSerializer<LocalDate> {
    override val descriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)
    
    override fun serialize(encoder: Encoder, value: LocalDate) {
        encoder.encodeString(value.toString())
    }
    
    override fun deserialize(decoder: Decoder): LocalDate {
        return LocalDate.parse(decoder.decodeString())
    }
}

Format Implementation Guidance

Descriptors help format implementations understand data structure:

fun encodeStructure(descriptor: SerialDescriptor, encoder: Encoder) {
    when (descriptor.kind) {
        StructureKind.CLASS -> encodeObject(descriptor, encoder)
        StructureKind.LIST -> encodeArray(descriptor, encoder) 
        StructureKind.MAP -> encodeMap(descriptor, encoder)
        is PrimitiveKind -> encodePrimitive(descriptor, encoder)
        else -> throw SerializationException("Unsupported kind: ${descriptor.kind}")
    }
}

Error Handling

Descriptor-related errors typically indicate structural mismatches:

  • IndexOutOfBoundsException: Invalid element index access
  • IllegalArgumentException: Invalid descriptor configurations
  • SerializationException: Descriptor/data structure mismatches during encoding/decoding

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-jvm

docs

annotations.md

built-ins.md

core-serialization.md

descriptors.md

encoding.md

index.md

modules.md

tile.json