0
# Descriptors System
1
2
The descriptors system provides structural metadata and introspection capabilities for serializable types. It enables format implementations to understand the structure of serializable classes without relying on reflection.
3
4
## Core Descriptor Interface
5
6
### SerialDescriptor
7
8
The main interface for describing the structure and metadata of serializable types.
9
10
```kotlin { .api }
11
interface SerialDescriptor {
12
val serialName: String
13
val kind: SerialKind
14
val elementsCount: Int
15
val annotations: List<Annotation>
16
val isNullable: Boolean
17
18
fun getElementName(index: Int): String
19
fun getElementIndex(name: String): Int
20
fun getElementAnnotations(index: Int): List<Annotation>
21
fun getElementDescriptor(index: Int): SerialDescriptor
22
fun isElementOptional(index: Int): Boolean
23
}
24
```
25
26
**Properties:**
27
- `serialName`: Unique name identifying the serializable class
28
- `kind`: The kind of serializable structure (class, list, map, etc.)
29
- `elementsCount`: Number of elements/properties in the descriptor
30
- `annotations`: Annotations applied to the class
31
- `isNullable`: Whether the type can be null
32
33
**Methods:**
34
- `getElementName(index)`: Gets the name of the element at the given index
35
- `getElementIndex(name)`: Gets the index of the element with the given name
36
- `getElementAnnotations(index)`: Gets annotations for the element at the given index
37
- `getElementDescriptor(index)`: Gets the nested descriptor for the element at the given index
38
- `isElementOptional(index)`: Checks if the element at the given index is optional
39
40
## Serial Kinds
41
42
Serial kinds categorize different types of serializable structures.
43
44
### Base SerialKind
45
46
```kotlin { .api }
47
sealed class SerialKind {
48
object ENUM : SerialKind()
49
object CONTEXTUAL : SerialKind()
50
}
51
```
52
53
### PrimitiveKind
54
55
Represents primitive types.
56
57
```kotlin { .api }
58
sealed class PrimitiveKind : SerialKind() {
59
object BOOLEAN : PrimitiveKind()
60
object BYTE : PrimitiveKind()
61
object CHAR : PrimitiveKind()
62
object SHORT : PrimitiveKind()
63
object INT : PrimitiveKind()
64
object LONG : PrimitiveKind()
65
object FLOAT : PrimitiveKind()
66
object DOUBLE : PrimitiveKind()
67
object STRING : PrimitiveKind()
68
}
69
```
70
71
### StructureKind
72
73
Represents structured types.
74
75
```kotlin { .api }
76
sealed class StructureKind : SerialKind() {
77
object CLASS : StructureKind()
78
object LIST : StructureKind()
79
object MAP : StructureKind()
80
object OBJECT : StructureKind()
81
}
82
```
83
84
### PolymorphicKind
85
86
Represents polymorphic types.
87
88
```kotlin { .api }
89
@ExperimentalSerializationApi
90
sealed class PolymorphicKind : SerialKind() {
91
object SEALED : PolymorphicKind()
92
object OPEN : PolymorphicKind()
93
}
94
```
95
96
## Descriptor Builder Functions
97
98
### buildClassSerialDescriptor
99
100
Creates a descriptor for class-like structures.
101
102
```kotlin { .api }
103
fun buildClassSerialDescriptor(
104
serialName: String,
105
vararg typeParameters: SerialDescriptor,
106
builderAction: ClassSerialDescriptorBuilder.() -> Unit = {}
107
): SerialDescriptor
108
```
109
110
**Usage:**
111
```kotlin
112
val userDescriptor = buildClassSerialDescriptor("User") {
113
element<String>("name")
114
element<String>("email")
115
element<Int>("age", isOptional = true)
116
}
117
```
118
119
### buildSerialDescriptor
120
121
Creates a generic descriptor with a specified kind.
122
123
```kotlin { .api }
124
fun buildSerialDescriptor(
125
serialName: String,
126
kind: SerialKind,
127
vararg typeParameters: SerialDescriptor,
128
builder: SerialDescriptorBuilder.() -> Unit = {}
129
): SerialDescriptor
130
```
131
132
### Collection Descriptor Builders
133
134
```kotlin { .api }
135
@ExperimentalSerializationApi
136
fun listSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor
137
138
@ExperimentalSerializationApi
139
inline fun <reified T> listSerialDescriptor(): SerialDescriptor
140
141
@ExperimentalSerializationApi
142
fun mapSerialDescriptor(
143
keyDescriptor: SerialDescriptor,
144
valueDescriptor: SerialDescriptor
145
): SerialDescriptor
146
147
@ExperimentalSerializationApi
148
inline fun <reified K, reified V> mapSerialDescriptor(): SerialDescriptor
149
150
@ExperimentalSerializationApi
151
fun setSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor
152
153
@ExperimentalSerializationApi
154
inline fun <reified T> setSerialDescriptor(): SerialDescriptor
155
```
156
157
**Usage:**
158
```kotlin
159
val stringListDescriptor = listSerialDescriptor(String.serializer().descriptor)
160
val intStringMapDescriptor = mapSerialDescriptor(
161
Int.serializer().descriptor,
162
String.serializer().descriptor
163
)
164
```
165
166
## Descriptor Builder Classes
167
168
### SerialDescriptorBuilder
169
170
Base builder for creating descriptors.
171
172
```kotlin { .api }
173
abstract class SerialDescriptorBuilder {
174
abstract fun element(
175
elementName: String,
176
descriptor: SerialDescriptor,
177
annotations: List<Annotation> = emptyList(),
178
isOptional: Boolean = false
179
)
180
181
inline fun <reified T> element(
182
elementName: String,
183
serializer: KSerializer<T> = serializer(),
184
annotations: List<Annotation> = emptyList(),
185
isOptional: Boolean = false
186
)
187
}
188
```
189
190
### ClassSerialDescriptorBuilder
191
192
Specialized builder for class descriptors.
193
194
```kotlin { .api }
195
class ClassSerialDescriptorBuilder(serialName: String) : SerialDescriptorBuilder() {
196
override fun element(
197
elementName: String,
198
descriptor: SerialDescriptor,
199
annotations: List<Annotation>,
200
isOptional: Boolean
201
)
202
}
203
```
204
205
**Usage:**
206
```kotlin
207
val descriptor = buildClassSerialDescriptor("Person") {
208
element<String>("firstName")
209
element<String>("lastName")
210
element<Int>("age", isOptional = true)
211
element("address", Address.serializer().descriptor, isOptional = true)
212
}
213
```
214
215
## Predefined Descriptors
216
217
### Primitive Descriptors
218
219
```kotlin { .api }
220
val BOOLEAN_DESCRIPTOR: SerialDescriptor
221
val BYTE_DESCRIPTOR: SerialDescriptor
222
val CHAR_DESCRIPTOR: SerialDescriptor
223
val SHORT_DESCRIPTOR: SerialDescriptor
224
val INT_DESCRIPTOR: SerialDescriptor
225
val LONG_DESCRIPTOR: SerialDescriptor
226
val FLOAT_DESCRIPTOR: SerialDescriptor
227
val DOUBLE_DESCRIPTOR: SerialDescriptor
228
val STRING_DESCRIPTOR: SerialDescriptor
229
val UNIT_DESCRIPTOR: SerialDescriptor
230
```
231
232
## Descriptor Annotations
233
234
### @ContextAware
235
236
Marks descriptors that require serialization context.
237
238
```kotlin { .api }
239
@Target(AnnotationTarget.CLASS)
240
annotation class ContextAware
241
```
242
243
## Descriptor Utilities
244
245
### Inline Descriptors
246
247
For inline value classes and primitive wrappers.
248
249
```kotlin { .api }
250
fun SerialDescriptor.getInlinedSerializer(): KSerializer<*>?
251
fun buildInlineDescriptor(
252
inlineSerializerName: String,
253
inlineValueDescriptor: SerialDescriptor
254
): SerialDescriptor
255
```
256
257
### Descriptor Equality and Hashing
258
259
```kotlin { .api }
260
fun SerialDescriptor.hashCodeImpl(): Int
261
fun SerialDescriptor.equalsImpl(other: SerialDescriptor): Boolean
262
```
263
264
## Usage Examples
265
266
### Custom Descriptor Creation
267
268
```kotlin
269
// Creating a descriptor for a custom data structure
270
val customDescriptor = buildClassSerialDescriptor("CustomData") {
271
element<String>("id")
272
element<List<String>>("tags")
273
element<Map<String, Any>>("metadata", isOptional = true)
274
}
275
276
// Using the descriptor to understand structure
277
println("Serial name: ${customDescriptor.serialName}")
278
println("Kind: ${customDescriptor.kind}")
279
println("Elements count: ${customDescriptor.elementsCount}")
280
281
// Using extension properties
282
for ((index, elementDescriptor) in customDescriptor.elementDescriptors.withIndex()) {
283
val elementName = customDescriptor.getElementName(index)
284
val isOptional = customDescriptor.isElementOptional(index)
285
286
println("Element $index: $elementName (${elementDescriptor.serialName}) - Optional: $isOptional")
287
}
288
289
// Iterate over element names
290
for (elementName in customDescriptor.elementNames) {
291
val index = customDescriptor.getElementIndex(elementName)
292
println("Element '$elementName' is at index $index")
293
}
294
```
295
296
### Working with Collections
297
298
```kotlin
299
// Descriptor for List<User>
300
val userListDescriptor = listSerialDescriptor(User.serializer().descriptor)
301
302
// Descriptor for Map<String, User>
303
val userMapDescriptor = mapSerialDescriptor(
304
String.serializer().descriptor,
305
User.serializer().descriptor
306
)
307
308
// Check descriptor properties
309
println("List kind: ${userListDescriptor.kind}") // StructureKind.LIST
310
println("Map kind: ${userMapDescriptor.kind}") // StructureKind.MAP
311
```