fun buildClassSerialDescriptor(serialName: String, vararg typeParameters: SerialDescriptor, builderAction: ClassSerialDescriptorBuilder.() -> Unit = {}): SerialDescriptor

Builder for SerialDescriptor. The resulting descriptor will be uniquely identified by the given serialName, typeParameters and elements structure described in builderAction function.


// Class with custom serializer and custom serial descriptor
class Data(
val intField: Int, // This field is ignored by custom serializer
val longField: Long, // This field is written as long, but in serialized form is named as "_longField"
val stringList: List<String> // This field is written as regular list of strings
val nullableInt: Int?
// Descriptor for such class:
buildClassSerialDescriptor("my.package.Data") {
// intField is deliberately ignored by serializer -- not present in the descriptor as well
element<Long>("_longField") // longField is named as _longField
element("stringField", listSerialDescriptor<String>()) // or ListSerializer(String.serializer()).descriptor
element("nullableInt", serialDescriptor<Int>().nullable)

Example for generic classes:

import kotlinx.serialization.builtins.*

class BoxedList<T>(val list: List<T>)

class CustomSerializer<T>(tSerializer: KSerializer<T>): KSerializer<BoxedList<T>> {
// here we use tSerializer.descriptor because it represents T
override val descriptor = buildClassSerialDescriptor("pkg.BoxedList", tSerializer.descriptor) {
// here we have to wrap it with List first, because property has type List<T>
element("list", ListSerializer(tSerializer).descriptor) // or listSerialDescriptor(tSerializer.descriptor)