1 /* 2 * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.serialization 6 7 import kotlinx.serialization.descriptors.* 8 import kotlinx.serialization.encoding.* 9 import kotlin.reflect.* 10 11 /** 12 * The main entry point to the serialization process. 13 * Applying [Serializable] to the Kotlin class instructs the serialization plugin to automatically generate implementation of [KSerializer] 14 * for the current class, that can be used to serialize and deserialize the class. 15 * The generated serializer can be accessed with `T.serializer()` extension function on the class companion, 16 * both are generated by the plugin as well. 17 * 18 * ``` 19 * @Serializable 20 * class MyData(val myData: AnotherData, val intProperty: Int, ...) 21 * 22 * // Produces JSON string using the generated serializer 23 * val jsonString = Json.encodeToJson(MyData.serializer(), instance) 24 * ``` 25 * 26 * Additionally, the user-defined serializer can be specified using [with] parameter: 27 * ``` 28 * @Serializable(with = MyAnotherDataCustomSerializer::class) 29 * class MyAnotherData(...) 30 * 31 * MyAnotherData.serializer() // <- returns MyAnotherDataCustomSerializer 32 * ``` 33 * 34 * To continue generating the implementation of [KSerializer] using the plugin, specify the [KeepGeneratedSerializer] annotation. 35 * In this case, the serializer will be available via `generatedSerializer()` function, and will also be used in the heirs. 36 * 37 * For annotated properties, specifying [with] parameter is mandatory and can be used to override 38 * serializer on the use-site without affecting the rest of the usages: 39 * ``` 40 * @Serializable // By default is serialized as 3 byte components 41 * class RgbPixel(val red: Short, val green: Short, val blue: Short) 42 * 43 * @Serializable 44 * class RgbExample( 45 * @Serializable(with = RgbAsHexString::class) p1: RgbPixel, // Serialize as HEX string, e.g. #FFFF00 46 * @Serializable(with = RgbAsSingleInt::class) p2: RgbPixel, // Serialize as single integer, e.g. 16711680 47 * p3: RgbPixel // Serialize as 3 short components, e.g. { "red": 255, "green": 255, "blue": 0 } 48 * ) 49 * ``` 50 * In this example, each pixel will be serialized using different data representation. 51 * 52 * For classes with generic type parameters, `serializer()` function requires one additional argument per each generic type parameter: 53 * ``` 54 * @Serializable 55 * class Box<T>(value: T) 56 * 57 * Box.serializer() // Doesn't compile 58 * Box.serializer(Int.serializer()) // Returns serializer for Box<Int> 59 * Box.serializer(Box.serializer(Int.serializer())) // Returns serializer for Box<Box<Int>> 60 * ``` 61 * 62 * ### Implementation details 63 * 64 * In order to generate `serializer` function that is not a method on the particular instance, the class should have a companion object, either named or unnamed. 65 * Companion object is generated by the plugin if it is not declared, effectively exposing both companion and `serializer()` method to class ABI. 66 * If companion object already exists, only `serializer` method will be generated. 67 * 68 * @see UseSerializers 69 * @see Serializer 70 * @see KeepGeneratedSerializer 71 */ 72 @MustBeDocumented 73 @Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS, AnnotationTarget.TYPE) 74 //@Retention(AnnotationRetention.RUNTIME) // Runtime is the default retention, also see KT-41082 75 public annotation class Serializable( 76 val with: KClass<out KSerializer<*>> = KSerializer::class // Default value indicates that auto-generated serializer is used 77 ) 78 79 /** 80 * The meta-annotation for adding [Serializable] behaviour to user-defined annotations. 81 * 82 * Applying [MetaSerializable] to the annotation class `A` instructs the serialization plugin to treat annotation A 83 * as [Serializable]. In addition, all annotations marked with [MetaSerializable] are saved in the generated [SerialDescriptor] 84 * as if they are annotated with [SerialInfo]. 85 * 86 * ``` 87 * @MetaSerializable 88 * @Target(AnnotationTarget.CLASS) 89 * annotation class MySerializable(val data: String) 90 * 91 * @MySerializable("some_data") 92 * class MyData(val myData: AnotherData, val intProperty: Int, ...) 93 * 94 * val serializer = MyData.serializer() 95 * serializer.descriptor.annotations.filterIsInstance<MySerializable>().first().data // <- returns "some_data" 96 * ``` 97 * 98 * @see Serializable 99 * @see SerialInfo 100 * @see UseSerializers 101 * @see Serializer 102 */ 103 @MustBeDocumented 104 @Target(AnnotationTarget.ANNOTATION_CLASS) 105 //@Retention(AnnotationRetention.RUNTIME) // Runtime is the default retention, also see KT-41082 106 @ExperimentalSerializationApi 107 public annotation class MetaSerializable 108 109 /** 110 * Instructs the serialization plugin to turn this class into serializer for specified class [forClass]. 111 * However, it would not be used automatically. To apply it on particular class or property, 112 * use [Serializable] or [UseSerializers], or [Contextual] with runtime registration. 113 * 114 * `@Serializer(forClass)` is experimental and unstable feature that can be changed in future releases. 115 * Changes may include additional constraints on classes and objects marked with this annotation, 116 * behavioural changes and even serialized shape of the class. 117 */ 118 @MustBeDocumented 119 @Target(AnnotationTarget.CLASS) 120 @Retention(AnnotationRetention.BINARY) 121 @ExperimentalSerializationApi 122 public annotation class Serializer( 123 val forClass: KClass<*> // target class to create serializer for 124 ) 125 126 /** 127 * Overrides the name of a class or a property in the corresponding [SerialDescriptor]. 128 * Names and serial names are used by text-based serial formats in order to encode the name of the class or 129 * the name of the property, e.g. by `Json`. 130 * 131 * By default, [SerialDescriptor.serialName] and [SerialDescriptor.getElementName] 132 * are associated with fully qualified name of the target class and the name of the property respectively. 133 * Applying this annotation changes the visible name to the given [value]: 134 * 135 * ``` 136 * package foo 137 * 138 * @Serializable // RegularName.serializer().descriptor.serialName is "foo.RegularName" 139 * class RegularName(val myInt: Int) 140 * 141 * @Serializable 142 * @SerialName("CustomName") // Omit package from name that is used for diagnostic and polymorphism 143 * class CustomName(@SerialName("int") val myInt: Int) 144 * 145 * // Prints "{"myInt":42}" 146 * println(Json.encodeToString(RegularName(42))) 147 * // Prints "{"int":42}" 148 * println(Json.encodeToString(CustomName(42))) 149 * ``` 150 * 151 * If a name of class or property is overridden with this annotation, original source code name is not available for the library. 152 * Tools like `JsonNamingStrategy` and `ProtoBufSchemaGenerator` would see and transform [value] from [SerialName] annotation. 153 */ 154 @MustBeDocumented 155 @Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS) 156 // @Retention(AnnotationRetention.RUNTIME) still runtime, but KT-41082 157 public annotation class SerialName(val value: String) 158 159 /** 160 * Indicates that property must be present during deserialization process, despite having a default value. 161 */ 162 @MustBeDocumented 163 @Target(AnnotationTarget.PROPERTY) 164 // @Retention(AnnotationRetention.RUNTIME) still runtime, but KT-41082 165 public annotation class Required 166 167 /** 168 * Marks this property invisible for the whole serialization process, including [serial descriptors][SerialDescriptor]. 169 * Transient properties must have default values. 170 */ 171 @MustBeDocumented 172 @Target(AnnotationTarget.PROPERTY) 173 // @Retention(AnnotationRetention.RUNTIME) still runtime, but KT-41082 174 public annotation class Transient 175 176 /** 177 * Controls whether the target property is serialized when its value is equal to a default value, 178 * regardless of the format settings. 179 * Does not affect decoding and deserialization process. 180 * 181 * Example of usage: 182 * ``` 183 * @Serializable 184 * data class Foo( 185 * @EncodeDefault(ALWAYS) val a: Int = 42, 186 * @EncodeDefault(NEVER) val b: Int = 43, 187 * val c: Int = 44 188 * ) 189 * 190 * Json { encodeDefaults = false }.encodeToString((Foo()) // {"a": 42} 191 * Json { encodeDefaults = true }.encodeToString((Foo()) // {"a": 42, "c":44} 192 * ``` 193 * 194 * @see EncodeDefault.Mode.ALWAYS 195 * @see EncodeDefault.Mode.NEVER 196 */ 197 @MustBeDocumented 198 @Target(AnnotationTarget.PROPERTY) 199 @ExperimentalSerializationApi 200 public annotation class EncodeDefault(val mode: Mode = Mode.ALWAYS) { 201 /** 202 * Strategy for the [EncodeDefault] annotation. 203 */ 204 @ExperimentalSerializationApi 205 public enum class Mode { 206 /** 207 * Configures serializer to always encode the property, even if its value is equal to its default. 208 * For annotated properties, format settings are not taken into account and 209 * [CompositeEncoder.shouldEncodeElementDefault] is not invoked. 210 */ 211 ALWAYS, 212 213 /** 214 * Configures serializer not to encode the property if its value is equal to its default. 215 * For annotated properties, format settings are not taken into account and 216 * [CompositeEncoder.shouldEncodeElementDefault] is not invoked. 217 */ 218 NEVER 219 } 220 } 221 222 /** 223 * Meta-annotation that commands the compiler plugin to handle the annotation as serialization-specific. 224 * Serialization-specific annotations are preserved in the [SerialDescriptor] and can be retrieved 225 * during serialization process with [SerialDescriptor.getElementAnnotations] for properties annotations 226 * and [SerialDescriptor.annotations] for class annotations. 227 * 228 * It is recommended to explicitly specify target for serial info annotations, whether it is [AnnotationTarget.PROPERTY], [AnnotationTarget.CLASS], or both. 229 * Keep in mind that Kotlin compiler prioritizes [function parameter target][AnnotationTarget.VALUE_PARAMETER] over [property target][AnnotationTarget.PROPERTY], 230 * so serial info annotations used on constructor-parameters-as-properties without explicit declaration-site or use-site target are not preserved. 231 */ 232 @MustBeDocumented 233 @Target(AnnotationTarget.ANNOTATION_CLASS) 234 @Retention(AnnotationRetention.BINARY) 235 @ExperimentalSerializationApi 236 public annotation class SerialInfo 237 238 /** 239 * Meta-annotation that commands the compiler plugin to handle the annotation as serialization-specific. 240 * Serialization-specific annotations are preserved in the [SerialDescriptor] and can be retrieved 241 * during serialization process with [SerialDescriptor.getElementAnnotations]. 242 * 243 * In contrary to regular [SerialInfo], this one makes annotations inheritable: 244 * If class X marked as [Serializable] has any of its supertypes annotated with annotation A that has `@InheritableSerialInfo` on it, 245 * A appears in X's [SerialDescriptor] even if X itself is not annotated. 246 * It is possible to use A multiple times on different supertypes. Resulting X's [SerialDescriptor.annotations] would still contain 247 * only one instance of A. 248 * Note that if A has any arguments, their values should be the same across all hierarchy. Otherwise, a compilation error 249 * would be reported by the plugin. 250 * 251 * Example: 252 * ``` 253 * @InheritableSerialInfo 254 * annotation class A(val value: Int) 255 * 256 * @A(1) // Annotation can also be inherited from interfaces 257 * interface I 258 * 259 * @Serializable 260 * @A(1) // Argument value is the same as in I, no compiler error 261 * abstract class Base: I 262 * 263 * @Serializable 264 * class Derived: Base() 265 * 266 * // This function returns 1. 267 * fun foo(): Int = Derived.serializer().descriptor.annotations.filterIsInstance<A>().single().value 268 * ``` 269 */ 270 @MustBeDocumented 271 @Target(AnnotationTarget.ANNOTATION_CLASS) 272 @Retention(AnnotationRetention.BINARY) 273 @ExperimentalSerializationApi 274 public annotation class InheritableSerialInfo 275 276 /** 277 * Instructs the plugin to use [ContextualSerializer] on a given property or type. 278 * Context serializer is usually used when serializer for type can only be found in runtime. 279 * It is also possible to apply [ContextualSerializer] to every property of the given type, 280 * using file-level [UseContextualSerialization] annotation. 281 * 282 * @see ContextualSerializer 283 * @see UseContextualSerialization 284 */ 285 @Target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE) 286 @Retention(AnnotationRetention.BINARY) 287 public annotation class Contextual 288 289 /** 290 * Instructs the plugin to use [ContextualSerializer] for every type in the current file that is listed in the [forClasses]. 291 * 292 * @see Contextual 293 * @see ContextualSerializer 294 */ 295 @Target(AnnotationTarget.FILE) 296 @Retention(AnnotationRetention.BINARY) 297 public annotation class UseContextualSerialization(vararg val forClasses: KClass<*>) 298 299 /** 300 * Adds [serializerClasses] to serializers resolving process inside the plugin. 301 * Each of [serializerClasses] must implement [KSerializer]. 302 * 303 * Inside the file with this annotation, for each given property 304 * of type `T` in some serializable class, this list would be inspected for the presence of `KSerializer<T>`. 305 * If such serializer is present, it would be used instead of default. 306 * 307 * Main use-case for this annotation is not to write @Serializable(with=SomeSerializer::class) 308 * on each property with custom serializer. 309 * 310 * Serializers from this list have higher priority than default, but lesser priority than 311 * serializers defined on the property itself, such as [Serializable] (with=...) or [Contextual]. 312 */ 313 @Target(AnnotationTarget.FILE) 314 @Retention(AnnotationRetention.BINARY) 315 public annotation class UseSerializers(vararg val serializerClasses: KClass<out KSerializer<*>>) 316 317 /** 318 * Instructs the serialization plugin to use [PolymorphicSerializer] on an annotated property or type usage. 319 * When used on class, replaces its serializer with [PolymorphicSerializer] everywhere. 320 * 321 * This annotation is applied automatically to interfaces and serializable abstract classes 322 * and can be applied to open classes in addition to [Serializable] for the sake of simplicity. 323 * 324 * Does not affect sealed classes, because they are gonna be serialized with subclasses automatically 325 * with special compiler plugin support which would be added later. 326 */ 327 @Target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE, AnnotationTarget.CLASS) 328 //@Retention(AnnotationRetention.RUNTIME) // Runtime is the default retention, also see KT-41082 329 public annotation class Polymorphic 330 331 /** 332 * Instructs the serialization plugin to keep automatically generated implementation of [KSerializer] 333 * for the current class if a custom serializer is specified at the same time `@Serializable(with=SomeSerializer::class)`. 334 * 335 * Automatically generated serializer is available via `generatedSerializer()` function in companion object of serializable class. 336 * 337 * Keeping generated serializers allow to use plugin generated serializer in inheritors even if custom serializer is specified. 338 * 339 * Used only with annotation [Serializable] with the specified argument [Serializable.with], e.g. `@Serializable(with=SomeSerializer::class)`. 340 * 341 * Annotation is not allowed on classes involved in polymorphic serialization: 342 * interfaces, sealed classes, abstract classes, classes marked by [Polymorphic]. 343 * 344 * A compiler version `2.0.20` or higher is required. 345 */ 346 @ExperimentalSerializationApi 347 @Target(AnnotationTarget.CLASS) 348 @Retention(AnnotationRetention.RUNTIME) 349 public annotation class KeepGeneratedSerializer 350 351 /** 352 * Marks declarations that are still **experimental** in kotlinx.serialization, which means that the design of the 353 * corresponding declarations has open issues which may (or may not) lead to their changes in the future. 354 * Roughly speaking, there is a chance that those declarations will be deprecated in the near future or 355 * the semantics of their behavior may change in some way that may break some code. 356 * 357 * By default, the following categories of API are experimental: 358 * 359 * * Writing 3rd-party serialization formats 360 * * Writing non-trivial custom serializers 361 * * Implementing [SerialDescriptor] interfaces 362 * * Not-yet-stable serialization formats that require additional polishing 363 */ 364 @MustBeDocumented 365 @Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS) 366 @RequiresOptIn(level = RequiresOptIn.Level.WARNING) 367 public annotation class ExperimentalSerializationApi 368 369 /** 370 * Public API marked with this annotation is effectively **internal**, which means 371 * it should not be used outside of `kotlinx.serialization`. 372 * Signature, semantics, source and binary compatibilities are not guaranteed for this API 373 * and will be changed without any warnings or migration aids. 374 * If you cannot avoid using internal API to solve your problem, please report your use-case to serialization's issue tracker. 375 */ 376 @MustBeDocumented 377 @Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.TYPEALIAS) 378 @RequiresOptIn(level = RequiresOptIn.Level.ERROR) 379 public annotation class InternalSerializationApi 380