@@ -11,16 +11,16 @@ import kotlinx.serialization.encoding.*
11
11
/* *
12
12
* Serial descriptor is an inherent property of [KSerializer] that describes the structure of the serializable type.
13
13
* The structure of the serializable type is not only the characteristic of the type itself, but also of the serializer as well,
14
- * meaning that one type can have multiple descriptors that have completely different structure .
14
+ * meaning that one type can have multiple descriptors that have completely different structures .
15
15
*
16
16
* For example, the class `class Color(val rgb: Int)` can have multiple serializable representations,
17
17
* such as `{"rgb": 255}`, `"#0000FF"`, `[0, 0, 255]` and `{"red": 0, "green": 0, "blue": 255}`.
18
- * Representations are determined by serializers and each such serializer has its own descriptor that identifies
18
+ * Representations are determined by serializers, and each such serializer has its own descriptor that identifies
19
19
* each structure in a distinguishable and format-agnostic manner.
20
20
*
21
21
* ### Structure
22
22
* Serial descriptor is identified by its [name][serialName] and consists of a kind, potentially empty set of
23
- * children elements and additional metadata.
23
+ * children elements, and additional metadata.
24
24
*
25
25
* * [serialName] uniquely identifies the descriptor (and the corresponding serializer) for non-generic types.
26
26
* For generic types, the actual type substitution is omitted from the string representation, and the name
@@ -29,7 +29,7 @@ import kotlinx.serialization.encoding.*
29
29
* arguments are not equal to each other.
30
30
* [serialName] is typically used to specify the type of the target class during serialization of polymorphic and sealed
31
31
* classes, for observability and diagnostics.
32
- * * [Kind][SerialKind] defines what this descriptor represents: primitive, enum, object, collection etc.
32
+ * * [Kind][SerialKind] defines what this descriptor represents: primitive, enum, object, collection, etc.
33
33
* * Children elements are represented as serial descriptors as well and define the structure of the type's elements.
34
34
* * Metadata carries additional information, such as [nullability][nullable], [optionality][isElementOptional]
35
35
* and [serial annotations][getElementAnnotations].
@@ -40,7 +40,7 @@ import kotlinx.serialization.encoding.*
40
40
* #### Serialization
41
41
* Serial descriptor is used as a bridge between decoders/encoders and serializers.
42
42
* When asking for a next element, the serializer provides an expected descriptor to the decoder, and,
43
- * based on the descriptor content, decoder decides how to parse its input.
43
+ * based on the descriptor content, the decoder decides how to parse its input.
44
44
* In JSON, for example, when the encoder is asked to encode the next element and this element
45
45
* is a subtype of [List], the encoder receives a descriptor with [StructureKind.LIST] and, based on that,
46
46
* first writes an opening square bracket before writing the content of the list.
@@ -51,7 +51,7 @@ import kotlinx.serialization.encoding.*
51
51
*
52
52
* #### Introspection
53
53
* Another usage of a serial descriptor is type introspection without its serialization.
54
- * Introspection can be used to check, whether the given serializable class complies the
54
+ * Introspection can be used to check whether the given serializable class complies the
55
55
* corresponding scheme and to generate JSON or ProtoBuf schema from the given class.
56
56
*
57
57
* ### Indices
@@ -60,13 +60,13 @@ import kotlinx.serialization.encoding.*
60
60
* the range from zero to [elementsCount] and represent and index of the property in this class.
61
61
* Consequently, primitives do not have children and their element count is zero.
62
62
*
63
- * For collections and maps indices don't have fixed bound. Regular collections descriptors usually
63
+ * For collections and maps indices do not have a fixed bound. Regular collections descriptors usually
64
64
* have one element (`T`, maps have two, one for keys and one for values), but potentially unlimited
65
- * number of actual children values. Valid indices range is not known statically
66
- * and implementations of such descriptor should provide consistent and unbounded names and indices.
65
+ * number of actual children values. Valid indices range is not known statically,
66
+ * and implementations of such a descriptor should provide consistent and unbounded names and indices.
67
67
*
68
68
* In practice, for regular classes it is allowed to invoke `getElement*(index)` methods
69
- * with an index from `0` to [elementsCount] range and element at the particular index corresponds to the
69
+ * with an index from `0` to [elementsCount] range and the element at the particular index corresponds to the
70
70
* serializable property at the given position.
71
71
* For collections and maps, index parameter for `getElement*(index)` methods is effectively bounded
72
72
* by the maximal number of collection/map elements.
@@ -80,12 +80,12 @@ import kotlinx.serialization.encoding.*
80
80
*
81
81
* An [equals] implementation should use both [serialName] and elements structure.
82
82
* Comparing [elementDescriptors] directly is discouraged,
83
- * because it may cause a stack overflow error, e.g. if a serializable class `T` contains elements of type `T`.
83
+ * because it may cause a stack overflow error, e.g., if a serializable class `T` contains elements of type `T`.
84
84
* To avoid it, a serial descriptor implementation should compare only descriptors
85
85
* of class' type parameters, in a way that `serializer<Box<Int>>().descriptor != serializer<Box<String>>().descriptor`.
86
- * If type parameters are equal, descriptors structure should be compared by using children elements
86
+ * If type parameters are equal, descriptor structure should be compared by using children elements
87
87
* descriptors' [serialName]s, which correspond to class names
88
- * (do not confuse with elements own names, which correspond to properties names); and/or other [SerialDescriptor]
88
+ * (do not confuse with elements' own names, which correspond to properties' names); and/or other [SerialDescriptor]
89
89
* properties, such as [kind].
90
90
* An example of [equals] implementation:
91
91
* ```
@@ -128,31 +128,29 @@ import kotlinx.serialization.encoding.*
128
128
* }
129
129
* ```
130
130
*
131
- * For a classes that are represented as a single primitive value, [PrimitiveSerialDescriptor] builder function can be used instead.
131
+ * For classes that are represented as a single primitive value, [PrimitiveSerialDescriptor] builder function can be used instead.
132
132
*
133
133
* ### Consistency violations
134
134
* An implementation of [SerialDescriptor] should be consistent with the implementation of the corresponding [KSerializer].
135
- * Yet it is not type-checked statically, thus making it possible to declare a non-consistent implementations of descriptor and serializer.
136
- * In such cases, the behaviour of an underlying format is unspecified and may lead to both runtime errors and encoding of
135
+ * Yet it is not type-checked statically, thus making it possible to declare a non-consistent implementation of descriptor and serializer.
136
+ * In such cases, the behavior of an underlying format is unspecified and may lead to both runtime errors and encoding of
137
137
* corrupted data that is impossible to decode back.
138
138
*
139
- * ### Not stable for inheritance
139
+ * ### Not for implementation
140
140
*
141
- * `SerialDescriptor` interface is not stable for inheritance in 3rd party libraries, as new methods
142
- * might be added to this interface or contracts of the existing methods can be changed.
143
- * This interface is safe to build using [buildClassSerialDescriptor] and [PrimitiveSerialDescriptor],
144
- * and is safe to delegate implementation to existing instances.
141
+ * `SerialDescriptor` interface should not be implemented in 3rd party libraries, as new methods
142
+ * might be added to this interface when kotlinx.serialization adds support for new Kotlin features.
143
+ * This interface is safe to use and construct via [buildClassSerialDescriptor], [PrimitiveSerialDescriptor], and `SerialDescriptor` factory function.
145
144
*/
146
145
public interface SerialDescriptor {
147
146
/* *
148
147
* Serial name of the descriptor that identifies a pair of the associated serializer and target class.
149
148
*
150
- * For generated and default serializers, the serial name should be equal to the corresponding class's fully- qualified name
149
+ * For generated and default serializers, the serial name is equal to the corresponding class's fully qualified name
151
150
* or, if overridden, [SerialName].
152
151
* Custom serializers should provide a unique serial name that identifies both the serializable class and
153
- * the serializer itself, ignoring type arguments, if they are present, for example: `my.package.LongAsTrimmedString`
152
+ * the serializer itself, ignoring type arguments if they are present, for example: `my.package.LongAsTrimmedString`.
154
153
*/
155
- @ExperimentalSerializationApi
156
154
public val serialName: String
157
155
158
156
/* *
@@ -163,16 +161,14 @@ public interface SerialDescriptor {
163
161
* brackets, while ProtoBuf just serialize these types in separate ways.
164
162
*
165
163
* Kind should be consistent with the implementation, for example, if it is a [primitive][PrimitiveKind],
166
- * then its elements count should be zero and vice versa.
164
+ * then its element count should be zero and vice versa.
167
165
*/
168
- @ExperimentalSerializationApi
169
166
public val kind: SerialKind
170
167
171
168
/* *
172
- * Whether the descriptor describes nullable element .
169
+ * Whether the descriptor describes a nullable type .
173
170
* Returns `true` if associated serializer can serialize/deserialize nullable elements of the described type.
174
171
*/
175
- @ExperimentalSerializationApi
176
172
public val isNullable: Boolean get() = false
177
173
178
174
/* *
@@ -192,15 +188,26 @@ public interface SerialDescriptor {
192
188
* the corresponding descriptor has a single element (`IntDescriptor`, the type of list element),
193
189
* but from zero up to `Int.MAX_VALUE` values in the serialized form.
194
190
*/
195
- @ExperimentalSerializationApi
196
191
public val elementsCount: Int
197
192
198
193
/* *
199
194
* Returns serial annotations of the associated class.
200
- * Serial annotations can be used to specify an additional metadata that may be used during serialization.
195
+ * Serial annotations can be used to specify additional metadata that may be used during serialization.
201
196
* Only annotations marked with [SerialInfo] are added to the resulting list.
197
+ *
198
+ * Do not confuse with [getElementAnnotations]:
199
+ * ```
200
+ * @Serializable
201
+ * @OnClassSerialAnnotation
202
+ * class Nested(...)
203
+ *
204
+ * @Serializable
205
+ * class Outer(@OnPropertySerialAnnotation val nested: Nested)
206
+ *
207
+ * outerDescriptor.getElementAnnotations(0) // Returns [@OnPropertySerialAnnotation]
208
+ * outerDescriptor.getElementDescriptor(0).annotations // Returns [@OnClassSerialAnnotation]
209
+ * ```
202
210
*/
203
- @ExperimentalSerializationApi
204
211
public val annotations: List <Annotation > get() = emptyList()
205
212
206
213
/* *
@@ -211,38 +218,35 @@ public interface SerialDescriptor {
211
218
* @throws IndexOutOfBoundsException for an illegal [index] values.
212
219
* @throws IllegalStateException if the current descriptor does not support children elements (e.g. is a primitive)
213
220
*/
214
- @ExperimentalSerializationApi
215
221
public fun getElementName (index : Int ): String
216
222
217
223
/* *
218
224
* Returns an index in the children list of the given element by its name or [CompositeDecoder.UNKNOWN_NAME]
219
225
* if there is no such element.
220
226
* The resulting index, if it is not [CompositeDecoder.UNKNOWN_NAME], is guaranteed to be usable with [getElementName].
221
227
*/
222
- @ExperimentalSerializationApi
223
228
public fun getElementIndex (name : String ): Int
224
229
225
230
/* *
226
231
* Returns serial annotations of the child element at the given [index].
227
232
* This method differs from `getElementDescriptor(index).annotations` by reporting only
228
- * declaration -specific annotations:
233
+ * element -specific annotations:
229
234
* ```
230
235
* @Serializable
231
- * @SomeSerialAnnotation
236
+ * @OnClassSerialAnnotation
232
237
* class Nested(...)
233
238
*
234
239
* @Serializable
235
- * class Outer(@AnotherSerialAnnotation val nested: Nested)
240
+ * class Outer(@OnPropertySerialAnnotation val nested: Nested)
236
241
*
237
- * outerDescriptor.getElementAnnotations(0) // Returns [@AnotherSerialAnnotation ]
238
- * outerDescriptor.getElementDescriptor(0).annotations // Returns [@SomeSerialAnnotation ]
242
+ * outerDescriptor.getElementAnnotations(0) // Returns [@OnPropertySerialAnnotation ]
243
+ * outerDescriptor.getElementDescriptor(0).annotations // Returns [@OnClassSerialAnnotation ]
239
244
* ```
240
245
* Only annotations marked with [SerialInfo] are added to the resulting list.
241
246
*
242
247
* @throws IndexOutOfBoundsException for an illegal [index] values.
243
248
* @throws IllegalStateException if the current descriptor does not support children elements (e.g. is a primitive).
244
249
*/
245
- @ExperimentalSerializationApi
246
250
public fun getElementAnnotations (index : Int ): List <Annotation >
247
251
248
252
/* *
@@ -252,17 +256,29 @@ public interface SerialDescriptor {
252
256
* with `@Serializable(with = ...`)`, [Polymorphic] or [Contextual].
253
257
* This method can be used to completely introspect the type that the current descriptor describes.
254
258
*
259
+ * Example:
260
+ * ```
261
+ * @Serializable
262
+ * @OnClassSerialAnnotation
263
+ * class Nested(...)
264
+ *
265
+ * @Serializable
266
+ * class Outer(val nested: Nested)
267
+ *
268
+ * outerDescriptor.getElementDescriptor(0).serialName // Returns "Nested"
269
+ * outerDescriptor.getElementDescriptor(0).annotations // Returns [@OnClassSerialAnnotation]
270
+ * ```
271
+ *
255
272
* @throws IndexOutOfBoundsException for illegal [index] values.
256
273
* @throws IllegalStateException if the current descriptor does not support children elements (e.g. is a primitive).
257
274
*/
258
- @ExperimentalSerializationApi
259
275
public fun getElementDescriptor (index : Int ): SerialDescriptor
260
276
261
277
/* *
262
278
* Whether the element at the given [index] is optional (can be absent in serialized form).
263
279
* For generated descriptors, all elements that have a corresponding default parameter value are
264
280
* marked as optional. Custom serializers can treat optional values in a serialization-specific manner
265
- * without default parameters constraint.
281
+ * without a default parameters constraint.
266
282
*
267
283
* Example of optionality:
268
284
* ```
@@ -275,19 +291,17 @@ public interface SerialDescriptor {
275
291
* val e: List<Int> = listOf(1), // Optional == true
276
292
* )
277
293
* ```
278
- * Returns `false` for valid indices of collections, maps and enums.
294
+ * Returns `false` for valid indices of collections, maps, and enums.
279
295
*
280
296
* @throws IndexOutOfBoundsException for an illegal [index] values.
281
297
* @throws IllegalStateException if the current descriptor does not support children elements (e.g. is a primitive).
282
298
*/
283
- @ExperimentalSerializationApi
284
299
public fun isElementOptional (index : Int ): Boolean
285
300
}
286
301
287
302
/* *
288
303
* Returns an iterable of all descriptor [elements][SerialDescriptor.getElementDescriptor].
289
304
*/
290
- @ExperimentalSerializationApi
291
305
public val SerialDescriptor .elementDescriptors: Iterable <SerialDescriptor >
292
306
get() = Iterable {
293
307
object : Iterator <SerialDescriptor > {
@@ -303,7 +317,6 @@ public val SerialDescriptor.elementDescriptors: Iterable<SerialDescriptor>
303
317
/* *
304
318
* Returns an iterable of all descriptor [element names][SerialDescriptor.getElementName].
305
319
*/
306
- @ExperimentalSerializationApi
307
320
public val SerialDescriptor .elementNames: Iterable <String >
308
321
get() = Iterable {
309
322
object : Iterator <String > {
0 commit comments