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