Kotlin multiplatform reflectionless serialization library core module for JavaScript platform
—
Comprehensive reference for all kotlinx.serialization annotations that control serialization behavior.
The primary annotation that marks a class as serializable and instructs the compiler plugin to generate a serializer.
@MustBeDocumented
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS, AnnotationTarget.TYPE)
public annotation class Serializable(
val with: KClass<out KSerializer<*>> = KSerializer::class
){ .api }
Usage:
// Basic serializable class
@Serializable
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// With custom serializer
@Serializable(UserCustomSerializer::class)
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}Parameters:
with: Specifies a custom serializer class to use instead of the generated oneOverrides the default name used in the serialized form for classes or properties.
@MustBeDocumented
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
public annotation class SerialName(val value: String){ .api }
Usage:
@Serializable
@SerialName("UserProfile")
class User {
@SerialName("user_name")
name;
@SerialName("user_age")
age;
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// Serialized as: {"user_name": "John", "user_age": 30}Marks a property as required during deserialization, even if it has a default value.
@SerialInfo
@Target(AnnotationTarget.PROPERTY)
annotation class Required{ .api }
Usage:
@Serializable
class Config {
@Required
apiKey = "default"; // Must be present in JSON even though it has default
timeout = 5000; // Optional, will use default if missing
constructor(apiKey = "default", timeout = 5000) {
this.apiKey = apiKey;
this.timeout = timeout;
}
}
// This will throw MissingFieldException:
// {"timeout": 10000} // Missing required apiKey
// This works:
// {"apiKey": "abc123", "timeout": 10000}Excludes a property from serialization entirely.
@Target(AnnotationTarget.PROPERTY)
annotation class Transient{ .api }
Usage:
@Serializable
class User {
name;
age;
@Transient
password; // Never serialized
@Transient
temporaryData; // Runtime-only data
constructor(name, age, password = null, temporaryData = null) {
this.name = name;
this.age = age;
this.password = password;
this.temporaryData = temporaryData;
}
}
// Only serializes: {"name": "John", "age": 30}Controls serialization of properties with default values (Experimental API).
@ExperimentalSerializationApi
@SerialInfo
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
annotation class EncodeDefault(val mode: Mode = Mode.ALWAYS) {
enum class Mode { ALWAYS, NEVER }
}{ .api }
Usage:
@Serializable
class Settings {
@EncodeDefault(EncodeDefault.Mode.ALWAYS)
theme = "dark"; // Always included, even when default
@EncodeDefault(EncodeDefault.Mode.NEVER)
debug = false; // Never included when it's the default value
language = "en"; // Format-dependent behavior
constructor(theme = "dark", debug = false, language = "en") {
this.theme = theme;
this.debug = debug;
this.language = language;
}
}Instructs the plugin to use contextual serializer lookup for this property.
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE)
annotation class Contextual{ .api }
Usage:
@Serializable
class Event {
name;
@Contextual
timestamp; // Serializer looked up from SerializersModule at runtime
constructor(name, timestamp) {
this.name = name;
this.timestamp = timestamp;
}
}
// Configure contextual serializer in module
const module = SerializersModule {
contextual(Date, DateSerializer)
};File-level annotation that enables contextual serialization for specified classes.
@Target(AnnotationTarget.FILE)
annotation class UseContextualSerialization(
vararg val forClasses: KClass<*>
){ .api }
Usage:
@file:UseContextualSerialization(Date::class, BigDecimal::class)
// Now all Date and BigDecimal properties automatically use contextual lookup
@Serializable
class Transaction {
timestamp; // Automatically contextual (Date)
amount; // Automatically contextual (BigDecimal)
constructor(timestamp, amount) {
this.timestamp = timestamp;
this.amount = amount;
}
}File-level annotation to add serializers to the resolving process.
@Target(AnnotationTarget.FILE)
annotation class UseSerializers(
vararg val serializerClasses: KClass<out KSerializer<*>>
){ .api }
Usage:
@file:UseSerializers(DateSerializer::class, UUIDSerializer::class)
// These serializers are now available for automatic resolution
@Serializable
class Document {
id; // Will use UUIDSerializer if id is UUID
createdAt; // Will use DateSerializer if createdAt is Date
constructor(id, createdAt) {
this.id = id;
this.createdAt = createdAt;
}
}Instructs the plugin to use polymorphic serialization for this property.
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.TYPE)
annotation class Polymorphic{ .api }
Usage:
@Serializable
abstract class Shape {
abstract area;
}
@Serializable
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
this.area = Math.PI * radius * radius;
}
}
@Serializable
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
this.area = width * height;
}
}
@Serializable
class Drawing {
@Polymorphic
shapes; // Array of Shape - actual type determined at runtime
constructor(shapes) {
this.shapes = shapes;
}
}Meta-annotation for creating custom serializable annotations (Experimental).
@ExperimentalSerializationApi
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class MetaSerializable{ .api }
Usage:
@MetaSerializable
@Target(AnnotationTarget.CLASS)
annotation class JsonSerializable
// Custom annotation that implies @Serializable
@JsonSerializable
class User {
constructor(name) {
this.name = name;
}
}Instructs the plugin to create a serializer for the specified class (Experimental).
@ExperimentalSerializationApi
@Target(AnnotationTarget.CLASS)
annotation class Serializer(val forClass: KClass<*>){ .api }
Usage:
// Generate serializer for external class you can't modify
@Serializer(ExternalLibraryClass::class)
object ExternalClassSerializer : KSerializer<ExternalLibraryClass> {
// Implementation generated by plugin
}Keeps the generated serializer accessible when a custom serializer is specified (Experimental).
@ExperimentalSerializationApi
@Target(AnnotationTarget.CLASS)
annotation class KeepGeneratedSerializer{ .api }
Usage:
@Serializable(CustomUserSerializer::class)
@KeepGeneratedSerializer
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
// Both CustomUserSerializer and generated serializer are available
static generatedSerializer = /* generated serializer */;
}
// Access both serializers
const customSer = User.serializer(); // Returns CustomUserSerializer
const generatedSer = User.generatedSerializer; // Returns generated serializerBase meta-annotation for all serialization-related annotations.
@ExperimentalSerializationApi
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class SerialInfo{ .api }
Meta-annotation for annotations that should be inherited by subclasses.
@ExperimentalSerializationApi
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class InheritableSerialInfo{ .api }
Usage:
@InheritableSerialInfo
@Target(AnnotationTarget.CLASS)
annotation class ApiVersion(val version: String)
@ApiVersion("v1")
@Serializable
abstract class BaseEntity {
id;
}
// Inherits @ApiVersion("v1") annotation
@Serializable
class User extends BaseEntity {
constructor(id, name) {
super();
this.id = id;
this.name = name;
}
}Annotations can be combined for sophisticated serialization control:
@Serializable
class UserProfile {
@SerialName("user_id")
@Required
id; // Custom name and always required
@SerialName("display_name")
name; // Custom name, optional
@Transient
password; // Never serialized
@Contextual
@SerialName("last_login")
lastLogin; // Custom name with contextual serializer
@EncodeDefault(EncodeDefault.Mode.NEVER)
theme = "default"; // Don't encode when default
constructor(id, name, password = null, lastLogin = null, theme = "default") {
this.id = id;
this.name = name;
this.password = password;
this.lastLogin = lastLogin;
this.theme = theme;
}
}On JavaScript, enum classes require explicit @Serializable annotation:
@Serializable
enum class Status {
ACTIVE, INACTIVE, PENDING
}
@Serializable
class Task {
status; // Status enum
constructor(status) {
this.status = status;
}
}TypeScript provides compile-time validation of annotation usage:
interface SerializableClass {
// Ensures proper annotation usage at compile time
readonly serializer: () => KSerializer<this>;
}
@Serializable
class User implements SerializableClass {
// TypeScript enforces correct implementation
}All annotations work consistently across different serialization formats (JSON, ProtoBuf, CBOR, etc.), providing format-independent serialization control.
Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-js