CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-js

Kotlin multiplatform reflectionless serialization library core module for JavaScript platform

Pending
Overview
Eval results
Files

serializers.mddocs/

Core Serializers

Complete reference for the KSerializer interface and core serialization strategies in kotlinx.serialization-core-js.

Core Interfaces

KSerializer<T>

The primary interface that combines serialization and deserialization capabilities.

interface KSerializer<T> : SerializationStrategy<T>, DeserializationStrategy<T> {
    val descriptor: SerialDescriptor
}

{ .api }

Usage:

// Get serializer for a class
const userSerializer = User.serializer();

// Use with any format
const json = format.encodeToString(userSerializer, user);
const decoded = format.decodeFromString(userSerializer, json);

// Access descriptor
console.log(userSerializer.descriptor.serialName); // "User"

SerializationStrategy<T>

Interface for types that can be serialized to a format.

interface SerializationStrategy<T> {
    val descriptor: SerialDescriptor
    fun serialize(encoder: Encoder, value: T)
}

{ .api }

Usage:

class CustomSerializationStrategy {
  constructor(descriptor) {
    this.descriptor = descriptor;
  }
  
  serialize(encoder, value) {
    // Custom serialization logic
    encoder.encodeString(value.toString());
  }
}

DeserializationStrategy<T>

Interface for types that can be deserialized from a format.

interface DeserializationStrategy<T> {
    val descriptor: SerialDescriptor  
    fun deserialize(decoder: Decoder): T
}

{ .api }

Usage:

class CustomDeserializationStrategy {
  constructor(descriptor) {
    this.descriptor = descriptor;
  }
  
  deserialize(decoder) {
    // Custom deserialization logic
    const str = decoder.decodeString();
    return parseCustomFormat(str);
  }
}

Serializer Factory Functions

serializer<T>()

Retrieves a serializer for a reified type T.

inline fun <reified T> serializer(): KSerializer<T>

{ .api }

Usage:

// For basic types
const stringSerializer = serializer<String>();
const intSerializer = serializer<Int>();

// For collections with type parameters
const listSerializer = serializer<List<String>>();
const mapSerializer = serializer<Map<String, Int>>();

// For custom classes
const userSerializer = serializer<User>();

SerializersModule.serializer<T>()

Retrieves a serializer with contextual lookup from a module.

inline fun <reified T> SerializersModule.serializer(): KSerializer<T>

{ .api }

Usage:

const module = SerializersModule {
  contextual(Date, CustomDateSerializer)
};

// Gets contextual serializer if available, otherwise default
const dateSerializer = module.serializer<Date>();

serializer(type: KType)

Creates a serializer for a given KType (includes nullability and generics).

fun serializer(type: KType): KSerializer<Any?>

{ .api }

Usage:

import { typeOf } from 'kotlin-stdlib-js';

// For nullable types
const nullableStringType = typeOf<String?>();
const nullableStringSerializer = serializer(nullableStringType);

// For generic types
const listOfStringType = typeOf<List<String>>();
const listSerializer = serializer(listOfStringType);

serializer(kClass, typeArgs, isNullable)

Creates a serializer for a KClass with type arguments (Experimental).

@ExperimentalSerializationApi
fun serializer(
    kClass: KClass<*>, 
    typeArgumentsSerializers: Array<KSerializer<*>>, 
    isNullable: Boolean
): KSerializer<Any?>

{ .api }

Usage:

// Create List<User> serializer
const userClass = User::class;
const userSerializer = serializer<User>();
const listUserSerializer = serializer(
  List::class, 
  [userSerializer], 
  false // not nullable
);

serializerOrNull(type: KType)

Creates a serializer for KType or returns null if unavailable.

fun serializerOrNull(type: KType): KSerializer<Any?>?

{ .api }

Usage:

const type = typeOf<SomeUnknownClass>();
const serializer = serializerOrNull(type);

if (serializer !== null) {
  // Safe to use serializer
  const json = format.encodeToString(serializer, value);
} else {
  console.log("No serializer available for type");
}

Special Serializers

ContextualSerializer<T>

Serializer that delegates to runtime lookup in SerializersModule (Experimental).

@ExperimentalSerializationApi
class ContextualSerializer<T : Any>(
    private val serializableClass: KClass<T>,
    private val fallbackSerializer: KSerializer<T>? = null,
    private val typeArgumentsSerializers: Array<KSerializer<*>> = emptyArray()
) : KSerializer<T>

{ .api }

Usage:

// Create contextual serializer for Date
const dateContextualSerializer = new ContextualSerializer(
  Date::class,
  DefaultDateSerializer, // fallback
  [] // no type arguments
);

// Use in SerializersModule
const module = SerializersModule {
  contextual(Date::class, CustomDateSerializer)
};

// When used with module, CustomDateSerializer will be used
// When used without module, DefaultDateSerializer will be used

PolymorphicSerializer<T>

Serializer for polymorphic serialization of class hierarchies.

class PolymorphicSerializer<T : Any>(private val baseClass: KClass<T>) : KSerializer<T>

{ .api }

Usage:

// Create polymorphic serializer for base class
const shapeSerializer = new PolymorphicSerializer(Shape::class);

// Configure subclasses in module
const module = SerializersModule {
  polymorphic(Shape::class) {
    subclass(Circle::class)
    subclass(Rectangle::class)
    subclass(Triangle::class)
  }
};

// Use with format configured with the module
const json = format.encodeToString(shapeSerializer, circleInstance);
// Output includes type discriminator: {"type":"Circle","radius":5}

SealedClassSerializer<T>

Internal serializer for sealed classes (handled automatically).

@InternalSerializationApi
class SealedClassSerializer<T : Any>(
    private val serialName: String,
    private val baseClass: KClass<T>, 
    private val subclassSerializers: Array<KSerializer<out T>>,
    private val subclassNames: Array<String>
) : KSerializer<T>

{ .api }

Usage:

// Sealed class (automatically gets SealedClassSerializer)
@Serializable
sealed class Result {
  @Serializable
  static class Success extends Result {
    constructor(data) {
      super();
      this.data = data;
    }
  }
  
  @Serializable
  static class Error extends Result {
    constructor(message) {
      super();
      this.message = message;
    }
  }
}

// Automatically uses SealedClassSerializer
const resultSerializer = Result.serializer();

Companion Object Serializers

Many standard types provide serializers through companion objects:

Primitive Type Serializers

// Companion object extensions
val Char.Companion.serializer: KSerializer<Char>
val Byte.Companion.serializer: KSerializer<Byte>
val Short.Companion.serializer: KSerializer<Short>
val Int.Companion.serializer: KSerializer<Int>
val Long.Companion.serializer: KSerializer<Long>
val Float.Companion.serializer: KSerializer<Float>
val Double.Companion.serializer: KSerializer<Double>
val Boolean.Companion.serializer: KSerializer<Boolean>
val String.Companion.serializer: KSerializer<String>

{ .api }

Usage:

// Access via companion objects
const charSer = Char.serializer();
const byteSer = Byte.serializer();
const shortSer = Short.serializer();
const intSer = Int.serializer();
const longSer = Long.serializer();
const floatSer = Float.serializer();
const doubleSer = Double.serializer();
const booleanSer = Boolean.serializer();
const stringSer = String.serializer();

Special Type Serializers

val Unit.serializer: KSerializer<Unit>
val UInt.Companion.serializer: KSerializer<UInt>
val ULong.Companion.serializer: KSerializer<ULong>
val UByte.Companion.serializer: KSerializer<UByte>
val UShort.Companion.serializer: KSerializer<UShort>
val Duration.Companion.serializer: KSerializer<Duration>

{ .api }

Usage:

const unitSer = Unit.serializer();
const uintSer = UInt.serializer();
const ulongSer = ULong.serializer();
const ubyteSer = UByte.serializer();
const ushortSer = UShort.serializer();
const durationSer = Duration.serializer();

Experimental Serializers

@ExperimentalSerializationApi
val Instant.Companion.serializer: KSerializer<Instant>

@ExperimentalSerializationApi  
val Uuid.Companion.serializer: KSerializer<Uuid>

{ .api }

Usage:

// Experimental APIs (may change)
const instantSer = Instant.serializer();
const uuidSer = Uuid.serializer();

Nullable Serializers

.nullable Property

All serializers can be made nullable using the .nullable property:

val KSerializer<T>.nullable: KSerializer<T?>

{ .api }

Usage:

// Make any serializer nullable
const stringSerializer = String.serializer();
const nullableStringSerializer = stringSerializer.nullable;

// Works with complex types too
const userSerializer = User.serializer();
const nullableUserSerializer = userSerializer.nullable;

// Use with collections
const listSerializer = ListSerializer(String.serializer());
const nullableListSerializer = listSerializer.nullable;

Custom Serializer Implementation

Basic Custom Serializer

class CustomUserSerializer {
  constructor() {
    this.descriptor = buildClassSerialDescriptor("CustomUser") {
      element("fullName", String.serializer().descriptor)
      element("birthYear", Int.serializer().descriptor)
    };
  }
  
  serialize(encoder, value) {
    const composite = encoder.beginStructure(this.descriptor);
    composite.encodeStringElement(this.descriptor, 0, `${value.firstName} ${value.lastName}`);
    composite.encodeIntElement(this.descriptor, 1, new Date().getFullYear() - value.age);
    composite.endStructure(this.descriptor);
  }
  
  deserialize(decoder) {
    const composite = decoder.beginStructure(this.descriptor);
    
    let fullName = "";
    let birthYear = 0;
    
    while (true) {
      const index = composite.decodeElementIndex(this.descriptor);
      if (index === CompositeDecoder.DECODE_DONE) break;
      
      switch (index) {
        case 0:
          fullName = composite.decodeStringElement(this.descriptor, 0);
          break;
        case 1:
          birthYear = composite.decodeIntElement(this.descriptor, 1);
          break;
        default:
          throw new SerializationException(`Unexpected index: ${index}`);
      }
    }
    
    composite.endStructure(this.descriptor);
    
    const parts = fullName.split(' ');
    const age = new Date().getFullYear() - birthYear;
    return new User(parts[0], parts[1], age);
  }
}

Using Custom Serializers

// Register with @Serializable
@Serializable(CustomUserSerializer::class)
class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
}

// Or use directly
const customSerializer = new CustomUserSerializer();
const json = format.encodeToString(customSerializer, user);
const decoded = format.decodeFromString(customSerializer, json);

Error Handling

Serializers can throw specific exceptions:

class ValidatingSerializer {
  serialize(encoder, value) {
    if (!this.isValid(value)) {
      throw new SerializationException("Invalid value for serialization");
    }
    // ... serialization logic
  }
  
  deserialize(decoder) {
    const result = /* ... deserialization logic */;
    
    if (!this.isValid(result)) {
      throw new SerializationException("Deserialized value failed validation");
    }
    
    return result;
  }
  
  isValid(value) {
    // Validation logic
    return value !== null && value !== undefined;
  }
}

TypeScript Integration

Serializers maintain full type safety in TypeScript:

// Typed serializer creation
const userSerializer: KSerializer<User> = User.serializer();
const listSerializer: KSerializer<Array<User>> = ListSerializer(userSerializer);

// Generic serializer functions
function serializeList<T>(serializer: KSerializer<T>, items: T[]): string {
  const listSer = ListSerializer(serializer);
  return format.encodeToString(listSer, items);
}

// Type-safe usage
const users: User[] = [new User("John", 30), new User("Jane", 25)];
const json: string = serializeList(User.serializer(), users);

The serializer system provides the foundation for all serialization operations while maintaining type safety and performance across different formats and use cases.

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-core-js

docs

annotations.md

builtins.md

descriptors.md

encoding.md

index.md

modules.md

serializers.md

tile.json