Kotlin multiplatform reflectionless serialization library core module for JavaScript platform
npx @tessl/cli install tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-js@1.9.0A powerful Kotlin multiplatform serialization library compiled for JavaScript that provides comprehensive type-safe serialization and deserialization capabilities for JavaScript/TypeScript applications.
Maven Package: org.jetbrains.kotlinx:kotlinx-serialization-core-js
Platform: Kotlin/JS
Language Support: JavaScript, TypeScript
API Level: Kotlin Serialization 1.6+
For Kotlin/JS projects, add to your build.gradle.kts:
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0")
}Or for Gradle with Groovy:
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-core:1.9.0'
}// Core serialization APIs
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.modules.*// Define a serializable data class
@Serializable
data class User(val name: String, val age: Int, val email: String)
// Create an instance
val user = User("John Doe", 30, "john@example.com")
// Get the serializer (requires a format like JSON)
val serializer = User.serializer()
// Usage with a format implementation (e.g., kotlinx-serialization-json):
// val json = Json.encodeToString(serializer, user)
// val deserializedUser = Json.decodeFromString(serializer, json)@Serializable
data class ApiResponse(
@SerialName("user_id") val userId: Int,
@SerialName("full_name") val fullName: String
)@Serializable
data class Profile(
@Required val username: String, // Must be present during deserialization
val bio: String = "", // Optional with default value
@Transient val temporaryData: String? = null // Excluded from serialization
)The kotlinx.serialization-core-js library is built around several key architectural components:
interface KSerializer<T> extends SerializationStrategy<T>, DeserializationStrategy<T> {
readonly descriptor: SerialDescriptor;
}
interface SerializationStrategy<T> {
serialize(encoder: Encoder, value: T): void;
}
interface DeserializationStrategy<T> {
deserialize(decoder: Decoder): T;
}Every serializable type has an associated SerialDescriptor that describes its structure:
The library separates serialization logic from format-specific encoding:
This architecture enables the same serializable classes to work with JSON, ProtoBuf, CBOR, and other formats.
Comprehensive annotation system for controlling serialization behavior:
@Serializable // Mark classes as serializable
@SerialName("custom") // Override property/class names
@Required // Require fields during deserialization
@Transient // Exclude fields from serialization
@Contextual // Use contextual serializer lookup
@Polymorphic // Enable polymorphic serialization→ Complete Annotations Reference
Built-in and factory serializers for all standard types:
// Retrieve serializers
serializer<String>() // For reified types
String.serializer() // Via companion object
ListSerializer(Int.serializer()) // Collection serializersIntrospect and describe serializable type structure:
val descriptor = User.serializer().descriptor
println(descriptor.serialName) // "User"
println(descriptor.kind) // StructureKind.CLASS
println(descriptor.elementsCount) // 3Low-level APIs for format implementors:
interface Encoder {
fun encodeString(value: String)
fun encodeInt(value: Int)
fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder
}Comprehensive serializers for Kotlin standard library types:
// Primitives and standard types
String.serializer()
Int.serializer()
Duration.serializer()
// Collections
ListSerializer(String.serializer())
MapSerializer(String.serializer(), Int.serializer())
// Arrays
IntArraySerializer()
ArraySerializer(String.serializer())→ Built-in Serializers Reference
Flexible module system for contextual and polymorphic serialization:
val module = SerializersModule {
contextual(LocalDateTime::class, LocalDateTimeSerializer)
polymorphic(Animal::class) {
subclass(Cat::class)
subclass(Dog::class)
}
}For JavaScript compatibility, use LongAsStringSerializer to avoid precision issues:
@Serializable
class TransactionRecord {
@Serializable(LongAsStringSerializer::class)
amount: string; // Serialized as string to preserve precision
constructor(amount: string) {
this.amount = amount;
}
}The library provides comprehensive TypeScript definitions:
// Serializer functions are typed
const userSerializer: KSerializer<User> = User.serializer();
// Generic serializers maintain type safety
const listSerializer: KSerializer<Array<string>> = ListSerializer(String.serializer());
// Format operations are fully typed
const users: Array<User> = format.decodeFromString(listSerializer, jsonString);@Serializable annotation on JavaScriptThe library provides specific exception types for different error conditions:
try {
const result = format.decodeFromString(serializer, invalidJson);
} catch (e) {
if (e instanceof SerializationException) {
console.log("Serialization error:", e.message);
} else if (e instanceof MissingFieldException) {
console.log("Missing required field:", e.missingFields);
}
}While kotlinx.serialization-core-js provides the serialization framework, it's designed to work with format-specific libraries:
// JSON format (separate library)
import { Json } from 'kotlinx-serialization-json-js';
const json = Json.Default;
const serialized = json.encodeToString(User.serializer(), user);
const deserialized = json.decodeFromString(User.serializer(), serialized);
// Other formats follow similar patterns
import { ProtoBuf } from 'kotlinx-serialization-protobuf-js';
import { Cbor } from 'kotlinx-serialization-cbor-js';This modular approach allows you to include only the formats your application needs while sharing the same serializable class definitions across all formats.