or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdbuiltins.mddescriptors.mdencoding.mdindex.mdmodules.mdserializers.md

modules.mddocs/

0

# Serializers Modules

1

2

Complete reference for SerializersModule and contextual serialization APIs that enable runtime serializer configuration in kotlinx.serialization-core-js.

3

4

## Core Module Class

5

6

### SerializersModule

7

8

Sealed class that holds a collection of serializers for runtime lookup.

9

10

```kotlin

11

public sealed class SerializersModule {

12

@ExperimentalSerializationApi

13

public abstract fun <T : Any> getContextual(

14

kClass: KClass<T>,

15

typeArgumentsSerializers: List<KSerializer<*>> = emptyList()

16

): KSerializer<T>?

17

18

@ExperimentalSerializationApi

19

public abstract fun <T : Any> getPolymorphic(baseClass: KClass<in T>, value: T): SerializationStrategy<T>?

20

21

@ExperimentalSerializationApi

22

public abstract fun <T : Any> getPolymorphic(baseClass: KClass<in T>, serializedClassName: String?): DeserializationStrategy<T>?

23

24

@ExperimentalSerializationApi

25

public abstract fun dumpTo(collector: SerializersModuleCollector)

26

}

27

```

28

{ .api }

29

30

**Usage:**

31

32

```javascript

33

// Basic module lookup

34

const module = SerializersModule {

35

contextual(Date::class, CustomDateSerializer)

36

};

37

38

// Get contextual serializer

39

const dateSerializer = module.getContextual(Date::class);

40

if (dateSerializer !== null) {

41

const json = format.encodeToString(dateSerializer, new Date());

42

}

43

44

// Polymorphic lookup

45

const shape = new Circle(5);

46

const shapeSerializer = module.getPolymorphic(Shape::class, shape);

47

```

48

49

## Module Factory Functions

50

51

### SerializersModule Builder

52

53

Primary DSL function for creating modules.

54

55

```kotlin

56

fun SerializersModule(builderAction: SerializersModuleBuilder.() -> Unit): SerializersModule

57

```

58

{ .api }

59

60

**Usage:**

61

62

```javascript

63

const module = SerializersModule {

64

// Add contextual serializers

65

contextual(Date::class, CustomDateSerializer)

66

contextual(BigDecimal::class, BigDecimalStringSerializer)

67

68

// Add polymorphic hierarchies

69

polymorphic(Shape::class) {

70

subclass(Circle::class)

71

subclass(Rectangle::class)

72

subclass(Triangle::class)

73

}

74

75

// Include other modules

76

include(otherModule)

77

};

78

```

79

80

### Empty Module

81

82

Factory for creating an empty module.

83

84

```kotlin

85

fun EmptySerializersModule(): SerializersModule

86

```

87

{ .api }

88

89

**Usage:**

90

91

```javascript

92

// Create empty module

93

const emptyModule = EmptySerializersModule();

94

95

// Use as base for building

96

const customModule = SerializersModule {

97

include(emptyModule)

98

contextual(String::class, CustomStringSerializer)

99

};

100

```

101

102

### Single Serializer Module

103

104

Factory functions for modules with a single serializer.

105

106

```kotlin

107

fun <T : Any> serializersModuleOf(

108

kClass: KClass<T>,

109

serializer: KSerializer<T>

110

): SerializersModule

111

112

inline fun <reified T : Any> serializersModuleOf(

113

serializer: KSerializer<T>

114

): SerializersModule

115

```

116

{ .api }

117

118

**Usage:**

119

120

```javascript

121

// Create module with single contextual serializer

122

const dateModule = serializersModuleOf(Date::class, CustomDateSerializer);

123

const reifiedDateModule = serializersModuleOf<Date>(CustomDateSerializer);

124

125

// Use in format configuration

126

const format = Json {

127

serializersModule = dateModule

128

};

129

```

130

131

## Module Builder

132

133

### SerializersModuleBuilder

134

135

Builder class for constructing SerializersModule instances.

136

137

```kotlin

138

class SerializersModuleBuilder {

139

fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>)

140

fun <T : Any> contextual(kClass: KClass<T>, provider: (typeArgumentsSerializers: List<KSerializer<*>>) -> KSerializer<*>)

141

142

fun <Base : Any> polymorphic(

143

baseClass: KClass<Base>,

144

actualClass: KClass<out Base>,

145

actualSerializer: KSerializer<out Base>

146

)

147

148

fun <Base : Any> polymorphicDefaultSerializer(

149

baseClass: KClass<Base>,

150

defaultSerializerProvider: (value: Base) -> SerializationStrategy<Base>?

151

)

152

153

fun <Base : Any> polymorphicDefaultDeserializer(

154

baseClass: KClass<Base>,

155

defaultDeserializerProvider: (className: String?) -> DeserializationStrategy<out Base>?

156

)

157

158

fun include(module: SerializersModule)

159

}

160

```

161

{ .api }

162

163

## Contextual Serialization

164

165

### Basic Contextual Registration

166

167

```javascript

168

// Register contextual serializers

169

const module = SerializersModule {

170

// Simple contextual registration

171

contextual(Date::class, CustomDateSerializer)

172

contextual(BigInteger::class, BigIntegerStringSerializer)

173

contextual(UUID::class, UUIDStringSerializer)

174

};

175

176

// Use in serializable classes

177

@Serializable

178

class Event {

179

name;

180

181

@Contextual

182

startTime; // Uses Date serializer from module

183

184

@Contextual

185

eventId; // Uses UUID serializer from module

186

187

constructor(name, startTime, eventId) {

188

this.name = name;

189

this.startTime = startTime;

190

this.eventId = eventId;

191

}

192

}

193

```

194

195

### Reified Contextual Registration

196

197

```kotlin

198

inline fun <reified T : Any> SerializersModuleBuilder.contextual(

199

serializer: KSerializer<T>

200

)

201

```

202

{ .api }

203

204

**Usage:**

205

206

```javascript

207

const module = SerializersModule {

208

// Reified contextual registration

209

contextual<Date>(CustomDateSerializer)

210

contextual<BigDecimal>(BigDecimalSerializer)

211

contextual<LocalDateTime>(LocalDateTimeSerializer)

212

};

213

```

214

215

### Generic Contextual Serializers

216

217

```kotlin

218

fun <T : Any> SerializersModuleBuilder.contextual(

219

kClass: KClass<T>,

220

provider: (typeArgumentsSerializers: List<KSerializer<*>>) -> KSerializer<*>

221

)

222

```

223

{ .api }

224

225

**Usage:**

226

227

```javascript

228

// Generic contextual serializer with type arguments

229

const module = SerializersModule {

230

contextual(Optional::class) { typeArgs ->

231

OptionalSerializer(typeArgs[0]) // Use first type argument

232

}

233

234

contextual(Result::class) { typeArgs ->

235

ResultSerializer(typeArgs[0]) // Generic Result<T> serializer

236

}

237

};

238

239

// Usage with generic types

240

@Serializable

241

class ApiResponse<T> {

242

@Contextual

243

data; // Optional<T> - serializer determined at runtime

244

245

status;

246

247

constructor(data, status) {

248

this.data = data;

249

this.status = status;

250

}

251

}

252

```

253

254

## Polymorphic Serialization

255

256

### Basic Polymorphic Registration

257

258

```javascript

259

const module = SerializersModule {

260

polymorphic(Shape::class) {

261

subclass(Circle::class)

262

subclass(Rectangle::class)

263

subclass(Triangle::class)

264

}

265

266

// Alternative syntax

267

polymorphic(Animal::class, Cat::class, Cat.serializer())

268

polymorphic(Animal::class, Dog::class, Dog.serializer())

269

};

270

```

271

272

### Polymorphic Module Builder

273

274

```kotlin

275

class PolymorphicModuleBuilder<Base : Any> {

276

fun <T : Base> subclass(kClass: KClass<T>)

277

fun <T : Base> subclass(kClass: KClass<T>, serializer: KSerializer<T>)

278

279

fun default(defaultSerializerProvider: (value: Base) -> SerializationStrategy<Base>?)

280

fun defaultDeserializer(defaultDeserializerProvider: (className: String?) -> DeserializationStrategy<out Base>?)

281

}

282

```

283

{ .api }

284

285

**Usage:**

286

287

```javascript

288

const module = SerializersModule {

289

polymorphic(Shape::class) {

290

// Register subclasses (uses generated serializers)

291

subclass(Circle::class)

292

subclass(Rectangle::class)

293

294

// Register with custom serializer

295

subclass(Triangle::class, TriangleCustomSerializer)

296

297

// Default serializer for unknown types

298

default { value ->

299

when (value) {

300

is UnknownShape -> UnknownShapeSerializer

301

else -> null

302

}

303

}

304

305

// Default deserializer for unknown class names

306

defaultDeserializer { className ->

307

when (className) {

308

"LegacyShape" -> LegacyShapeSerializer

309

else -> null

310

}

311

}

312

}

313

};

314

```

315

316

### Reified Polymorphic Registration

317

318

```kotlin

319

inline fun <reified T : Base> PolymorphicModuleBuilder<Base>.subclass()

320

inline fun <reified T : Base> PolymorphicModuleBuilder<Base>.subclass(serializer: KSerializer<T>)

321

```

322

{ .api }

323

324

**Usage:**

325

326

```javascript

327

const module = SerializersModule {

328

polymorphic(Shape::class) {

329

// Reified subclass registration

330

subclass<Circle>()

331

subclass<Rectangle>()

332

subclass<Triangle>(TriangleCustomSerializer)

333

}

334

};

335

```

336

337

## Advanced Polymorphic Configuration

338

339

### Custom Base Serializer

340

341

```javascript

342

const module = SerializersModule {

343

// Register polymorphic hierarchy with custom base serializer

344

polymorphic(

345

Shape::class,

346

Shape::class, // base class

347

ShapeBaseSerializer // custom base serializer

348

) {

349

subclass(Circle::class)

350

subclass(Rectangle::class)

351

}

352

};

353

```

354

355

### Default Providers

356

357

```javascript

358

const module = SerializersModule {

359

polymorphic(ApiResponse::class) {

360

subclass(SuccessResponse::class)

361

subclass(ErrorResponse::class)

362

363

// Handle serialization of unknown subtypes

364

default { value ->

365

if (value instanceof UnknownResponse) {

366

return UnknownResponseSerializer;

367

}

368

return null; // Will throw if no serializer found

369

}

370

371

// Handle deserialization of unknown type names

372

defaultDeserializer { className ->

373

if (className === "LegacyResponse") {

374

return LegacyResponseSerializer;

375

}

376

if (className === null) {

377

return DefaultResponseSerializer;

378

}

379

return null;

380

}

381

}

382

};

383

```

384

385

## Module Operations

386

387

### Module Combination

388

389

```kotlin

390

operator fun SerializersModule.plus(other: SerializersModule): SerializersModule

391

392

fun SerializersModule.overwriteWith(other: SerializersModule): SerializersModule

393

```

394

{ .api }

395

396

**Usage:**

397

398

```javascript

399

// Combine modules (first module takes precedence for conflicts)

400

const baseModule = SerializersModule {

401

contextual(Date::class, DefaultDateSerializer)

402

polymorphic(Shape::class) {

403

subclass(Circle::class)

404

}

405

};

406

407

const extensionModule = SerializersModule {

408

contextual(Date::class, CustomDateSerializer) // This will be ignored

409

contextual(BigDecimal::class, BigDecimalSerializer)

410

polymorphic(Shape::class) {

411

subclass(Rectangle::class)

412

}

413

};

414

415

val combinedModule = baseModule + extensionModule;

416

417

// Overwrite combination (second module takes precedence)

418

const overwrittenModule = baseModule.overwriteWith(extensionModule);

419

// Now uses CustomDateSerializer instead of DefaultDateSerializer

420

```

421

422

### Module Inclusion

423

424

```javascript

425

// Include existing modules in new ones

426

const coreModule = SerializersModule {

427

contextual(Date::class, DateSerializer)

428

contextual(UUID::class, UUIDSerializer)

429

};

430

431

const extendedModule = SerializersModule {

432

include(coreModule) // Include all registrations from coreModule

433

434

contextual(BigDecimal::class, BigDecimalSerializer)

435

polymorphic(Shape::class) {

436

subclass(Circle::class)

437

}

438

};

439

```

440

441

## Module Introspection

442

443

### SerializersModuleCollector

444

445

Interface for visiting module contents (Experimental).

446

447

```kotlin

448

@ExperimentalSerializationApi

449

interface SerializersModuleCollector {

450

fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>)

451

fun <Base : Any, Sub : Base> polymorphic(

452

baseClass: KClass<Base>,

453

actualClass: KClass<Sub>,

454

actualSerializer: KSerializer<Sub>

455

)

456

fun <Base : Any> polymorphicDefaultSerializer(

457

baseClass: KClass<Base>,

458

defaultSerializerProvider: (value: Base) -> SerializationStrategy<Base>?

459

)

460

fun <Base : Any> polymorphicDefaultDeserializer(

461

baseClass: KClass<Base>,

462

defaultDeserializerProvider: (className: String?) -> DeserializationStrategy<out Base>?

463

)

464

}

465

```

466

{ .api }

467

468

**Usage:**

469

470

```javascript

471

// Collect and inspect module contents

472

class ModuleInspector {

473

constructor() {

474

this.contextualSerializers = new Map();

475

this.polymorphicSerializers = new Map();

476

}

477

478

contextual(kClass, serializer) {

479

console.log(`Contextual: ${kClass.simpleName} -> ${serializer.constructor.name}`);

480

this.contextualSerializers.set(kClass, serializer);

481

}

482

483

polymorphic(baseClass, actualClass, actualSerializer) {

484

console.log(`Polymorphic: ${baseClass.simpleName} -> ${actualClass.simpleName}`);

485

486

if (!this.polymorphicSerializers.has(baseClass)) {

487

this.polymorphicSerializers.set(baseClass, new Map());

488

}

489

this.polymorphicSerializers.get(baseClass).set(actualClass, actualSerializer);

490

}

491

492

polymorphicDefaultSerializer(baseClass, provider) {

493

console.log(`Default serializer for ${baseClass.simpleName}`);

494

}

495

496

polymorphicDefaultDeserializer(baseClass, provider) {

497

console.log(`Default deserializer for ${baseClass.simpleName}`);

498

}

499

}

500

501

// Inspect module

502

const inspector = new ModuleInspector();

503

module.dumpTo(inspector);

504

505

console.log("Contextual serializers:", inspector.contextualSerializers);

506

console.log("Polymorphic serializers:", inspector.polymorphicSerializers);

507

```

508

509

## Format Integration

510

511

### Using Modules with Formats

512

513

```javascript

514

// Configure JSON format with module

515

const module = SerializersModule {

516

contextual(Date::class, ISO8601DateSerializer)

517

contextual(BigDecimal::class, BigDecimalStringSerializer)

518

519

polymorphic(ApiResponse::class) {

520

subclass(SuccessResponse::class)

521

subclass(ErrorResponse::class)

522

}

523

};

524

525

const json = Json {

526

serializersModule = module

527

ignoreUnknownKeys = true

528

encodeDefaults = false

529

};

530

531

// All serialization operations use the module

532

@Serializable

533

class ApiCall {

534

@Contextual

535

timestamp; // Uses ISO8601DateSerializer

536

537

@Contextual

538

amount; // Uses BigDecimalStringSerializer

539

540

@Polymorphic

541

response; // Uses polymorphic serialization

542

543

constructor(timestamp, amount, response) {

544

this.timestamp = timestamp;

545

this.amount = amount;

546

this.response = response;

547

}

548

}

549

550

const call = new ApiCall(new Date(), new BigDecimal("123.45"), new SuccessResponse("OK"));

551

const jsonString = json.encodeToString(ApiCall.serializer(), call);

552

```

553

554

## Real-World Examples

555

556

### Complete Application Module

557

558

```javascript

559

// Comprehensive module for a real application

560

const applicationModule = SerializersModule {

561

// Date/time serialization

562

contextual(Date::class, ISO8601DateSerializer)

563

contextual(LocalDateTime::class, LocalDateTimeComponentSerializer)

564

contextual(Duration::class, DurationStringSerializer)

565

566

// Numeric types for precision

567

contextual(BigDecimal::class, BigDecimalStringSerializer)

568

contextual(Long::class, LongAsStringSerializer)

569

570

// Identity types

571

contextual(UUID::class, UUIDStringSerializer)

572

573

// API response hierarchy

574

polymorphic(ApiResponse::class) {

575

subclass(SuccessResponse::class)

576

subclass(ErrorResponse::class)

577

subclass(ValidationErrorResponse::class)

578

579

default { response ->

580

when (response.type) {

581

"unknown" -> UnknownResponseSerializer

582

else -> null

583

}

584

}

585

}

586

587

// Domain model hierarchy

588

polymorphic(DomainEvent::class) {

589

subclass(UserCreatedEvent::class)

590

subclass(OrderPlacedEvent::class)

591

subclass(PaymentProcessedEvent::class)

592

}

593

594

// Generic result type

595

contextual(Result::class) { typeArgs ->

596

ResultSerializer(

597

successSerializer = typeArgs[0],

598

errorSerializer = typeArgs.getOrNull(1) ?: String.serializer()

599

)

600

}

601

};

602

```

603

604

### Module Composition Pattern

605

606

```javascript

607

// Modular approach with separate concerns

608

const dateTimeModule = SerializersModule {

609

contextual(Date::class, ISO8601DateSerializer)

610

contextual(LocalDateTime::class, LocalDateTimeSerializer)

611

contextual(Duration::class, DurationISOSerializer)

612

};

613

614

const numericModule = SerializersModule {

615

contextual(BigDecimal::class, BigDecimalStringSerializer)

616

contextual(Long::class, LongAsStringSerializer)

617

};

618

619

const apiModule = SerializersModule {

620

polymorphic(ApiResponse::class) {

621

subclass(SuccessResponse::class)

622

subclass(ErrorResponse::class)

623

}

624

};

625

626

const domainModule = SerializersModule {

627

polymorphic(DomainEvent::class) {

628

subclass(UserCreatedEvent::class)

629

subclass(OrderPlacedEvent::class)

630

}

631

};

632

633

// Compose final application module

634

const applicationModule = SerializersModule {

635

include(dateTimeModule)

636

include(numericModule)

637

include(apiModule)

638

include(domainModule)

639

};

640

641

// Use in different configurations

642

const jsonConfig = Json {

643

serializersModule = applicationModule

644

ignoreUnknownKeys = true

645

};

646

647

const protobufConfig = ProtoBuf {

648

serializersModule = applicationModule

649

};

650

```

651

652

SerializersModule provides a powerful and flexible system for runtime serializer configuration, enabling complex serialization scenarios while maintaining type safety and performance across different formats.