or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtins.mdcore-api.mddescriptors.mdencoding.mdindex.mdmodules.md

modules.mddocs/

0

# Serializers Module

1

2

The serializers module system provides runtime resolution of contextual and polymorphic serializers, enabling flexible serialization strategies that can be configured at runtime rather than compile time.

3

4

## Core Module Classes

5

6

### SerializersModule

7

8

Container for contextual and polymorphic serializers that can be queried at runtime.

9

10

```kotlin { .api }

11

sealed class SerializersModule {

12

@ExperimentalSerializationApi

13

abstract fun <T : Any> getContextual(

14

kClass: KClass<T>,

15

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

16

): KSerializer<T>?

17

18

@ExperimentalSerializationApi

19

abstract fun <T : Any> getPolymorphic(

20

baseClass: KClass<in T>,

21

value: T

22

): SerializationStrategy<T>?

23

24

@ExperimentalSerializationApi

25

abstract fun <T : Any> getPolymorphic(

26

baseClass: KClass<in T>,

27

serializedClassName: String?

28

): DeserializationStrategy<T>?

29

30

@ExperimentalSerializationApi

31

abstract fun dumpTo(collector: SerializersModuleCollector)

32

}

33

```

34

35

### SerializersModuleCollector

36

37

Base interface for collecting serializer registrations.

38

39

```kotlin { .api }

40

@ExperimentalSerializationApi

41

interface SerializersModuleCollector {

42

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

43

fun <T : Any> contextual(

44

kClass: KClass<T>,

45

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

46

)

47

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

48

baseClass: KClass<Base>,

49

actualClass: KClass<Sub>,

50

actualSerializer: KSerializer<Sub>

51

)

52

fun <Base : Any> polymorphicDefaultSerializer(

53

baseClass: KClass<Base>,

54

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

55

)

56

fun <Base : Any> polymorphicDefaultDeserializer(

57

baseClass: KClass<Base>,

58

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

59

)

60

}

61

```

62

63

### SerializersModuleBuilder

64

65

Builder for constructing SerializersModule instances.

66

67

```kotlin { .api }

68

class SerializersModuleBuilder : SerializersModuleCollector {

69

// Overrides from SerializersModuleCollector (inherited methods)

70

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

71

override fun <T : Any> contextual(

72

kClass: KClass<T>,

73

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

74

)

75

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

76

baseClass: KClass<Base>,

77

actualClass: KClass<Sub>,

78

actualSerializer: KSerializer<Sub>

79

)

80

override fun <Base : Any> polymorphicDefaultSerializer(

81

baseClass: KClass<Base>,

82

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

83

)

84

override fun <Base : Any> polymorphicDefaultDeserializer(

85

baseClass: KClass<Base>,

86

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

87

)

88

89

// Additional methods specific to builder

90

fun include(module: SerializersModule)

91

}

92

```

93

94

## Module Building Functions

95

96

### SerializersModule Constructor

97

98

Creates a new SerializersModule using a builder pattern.

99

100

```kotlin { .api }

101

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

102

```

103

104

### Factory Functions

105

106

```kotlin { .api }

107

fun EmptySerializersModule(): SerializersModule

108

109

@Deprecated("Replaced with EmptySerializersModule()")

110

val EmptySerializersModule: SerializersModule

111

112

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

113

114

infix fun SerializersModule.overwriteWith(other: SerializersModule): SerializersModule

115

116

fun <T : Any> serializersModuleOf(

117

kClass: KClass<T>,

118

serializer: KSerializer<T>

119

): SerializersModule

120

121

inline fun <reified T : Any> serializersModuleOf(

122

serializer: KSerializer<T>

123

): SerializersModule

124

```

125

126

## Polymorphic Module Builder

127

128

### PolymorphicModuleBuilder

129

130

Specialized builder for configuring polymorphic serialization within a specific base class.

131

132

```kotlin { .api }

133

class PolymorphicModuleBuilder<Base : Any> {

134

fun <Sub : Base> subclass(clazz: KClass<Sub>, serializer: KSerializer<Sub>)

135

inline fun <reified Sub : Base> subclass(serializer: KSerializer<Sub>)

136

137

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

138

fun defaultDeserializer(

139

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

140

)

141

}

142

```

143

144

**Extension Functions:**

145

```kotlin { .api }

146

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

147

148

inline fun <Base : Any> SerializersModuleBuilder.polymorphic(

149

baseClass: KClass<Base>,

150

baseSerializer: KSerializer<Base>? = null,

151

builderAction: PolymorphicModuleBuilder<Base>.() -> Unit

152

)

153

```

154

155

## Usage Examples

156

157

### Basic Module Creation

158

159

```kotlin

160

val module = SerializersModule {

161

// Register contextual serializers

162

contextual(LocalDateTime::class, LocalDateTimeSerializer)

163

contextual<BigDecimal>(BigDecimalSerializer)

164

165

// Register polymorphic serializers

166

polymorphic(Animal::class) {

167

subclass(Dog::class, Dog.serializer())

168

subclass(Cat::class, Cat.serializer())

169

}

170

}

171

```

172

173

### Contextual Serialization

174

175

```kotlin

176

// Define a contextual serializer for external types

177

object LocalDateTimeSerializer : KSerializer<LocalDateTime> {

178

override val descriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)

179

180

override fun serialize(encoder: Encoder, value: LocalDateTime) {

181

encoder.encodeString(value.toString())

182

}

183

184

override fun deserialize(decoder: Decoder): LocalDateTime {

185

return LocalDateTime.parse(decoder.decodeString())

186

}

187

}

188

189

// Register the contextual serializer

190

val module = SerializersModule {

191

contextual(LocalDateTime::class, LocalDateTimeSerializer)

192

}

193

194

// Use with @Contextual annotation

195

@Serializable

196

data class Event(

197

val name: String,

198

@Contextual

199

val timestamp: LocalDateTime

200

)

201

```

202

203

### Polymorphic Serialization

204

205

```kotlin

206

@Serializable

207

sealed class Animal {

208

abstract val name: String

209

}

210

211

@Serializable

212

@SerialName("dog")

213

data class Dog(override val name: String, val breed: String) : Animal()

214

215

@Serializable

216

@SerialName("cat")

217

data class Cat(override val name: String, val isIndoor: Boolean) : Animal()

218

219

// Configure polymorphic module

220

val module = SerializersModule {

221

polymorphic(Animal::class) {

222

subclass(Dog::class, Dog.serializer())

223

subclass(Cat::class, Cat.serializer())

224

}

225

}

226

227

// Usage with polymorphic property

228

@Serializable

229

data class Owner(

230

val name: String,

231

@Polymorphic

232

val pet: Animal

233

)

234

```

235

236

### Advanced Polymorphic Configuration

237

238

```kotlin

239

sealed class Shape

240

241

@Serializable

242

@SerialName("circle")

243

data class Circle(val radius: Double) : Shape()

244

245

@Serializable

246

@SerialName("rectangle")

247

data class Rectangle(val width: Double, val height: Double) : Shape()

248

249

val module = SerializersModule {

250

polymorphic(Shape::class) {

251

subclass(Circle::class, Circle.serializer())

252

subclass(Rectangle::class, Rectangle.serializer())

253

254

// Default serializer for unknown types during serialization

255

default { value ->

256

when (value) {

257

is Circle -> Circle.serializer()

258

is Rectangle -> Rectangle.serializer()

259

else -> null

260

}

261

}

262

263

// Default deserializer for unknown class names during deserialization

264

defaultDeserializer { className ->

265

when (className) {

266

"legacy_circle" -> Circle.serializer()

267

"legacy_rect" -> Rectangle.serializer()

268

else -> null

269

}

270

}

271

}

272

}

273

```

274

275

### Generic Type Contextual Serializers

276

277

```kotlin

278

// Custom serializer for generic types

279

class ListAsStringSerializer<T>(

280

private val elementSerializer: KSerializer<T>

281

) : KSerializer<List<T>> {

282

override val descriptor = PrimitiveSerialDescriptor("ListAsString", PrimitiveKind.STRING)

283

284

override fun serialize(encoder: Encoder, value: List<T>) {

285

val json = value.joinToString(",") { element ->

286

Json.encodeToString(elementSerializer, element)

287

}

288

encoder.encodeString("[$json]")

289

}

290

291

override fun deserialize(decoder: Decoder): List<T> {

292

val jsonString = decoder.decodeString()

293

// Parse and deserialize elements...

294

TODO("Implement parsing logic")

295

}

296

}

297

298

// Register with type parameter support

299

val module = SerializersModule {

300

contextual(List::class) { typeArgs ->

301

@Suppress("UNCHECKED_CAST")

302

ListAsStringSerializer(typeArgs[0] as KSerializer<Any>)

303

}

304

}

305

```

306

307

### Module Composition

308

309

```kotlin

310

val baseModule = SerializersModule {

311

contextual(UUID::class, UUIDSerializer)

312

contextual(LocalDate::class, LocalDateSerializer)

313

}

314

315

val extendedModule = SerializersModule {

316

include(baseModule)

317

318

contextual(ZonedDateTime::class, ZonedDateTimeSerializer)

319

320

polymorphic(Event::class) {

321

subclass(UserEvent::class, UserEvent.serializer())

322

subclass(SystemEvent::class, SystemEvent.serializer())

323

}

324

}

325

326

// Combine modules using plus operator

327

val combinedModule = baseModule + extendedModule

328

```

329

330

### Runtime Serializer Resolution

331

332

```kotlin

333

val module = SerializersModule {

334

contextual(BigInteger::class, BigIntegerSerializer)

335

polymorphic(Animal::class) {

336

subclass(Dog::class, Dog.serializer())

337

subclass(Cat::class, Cat.serializer())

338

}

339

}

340

341

// Query contextual serializers

342

val bigIntSerializer = module.getContextual(BigInteger::class)

343

println("Found contextual serializer: ${bigIntSerializer != null}")

344

345

// Query polymorphic serializers

346

val dogInstance = Dog("Buddy", "Golden Retriever")

347

val dogSerializer = module.getPolymorphic(Animal::class, dogInstance)

348

println("Found polymorphic serializer: ${dogSerializer != null}")

349

350

// Query by class name for deserialization

351

val catDeserializer = module.getPolymorphic(Animal::class, "cat")

352

println("Found deserializer for 'cat': ${catDeserializer != null}")

353

```

354

355

### Integration with Formats

356

357

```kotlin

358

val module = SerializersModule {

359

contextual(LocalDateTime::class, LocalDateTimeSerializer)

360

polymorphic(Shape::class) {

361

subclass(Circle::class, Circle.serializer())

362

subclass(Rectangle::class, Rectangle.serializer())

363

}

364

}

365

366

// Use with JSON format (requires kotlinx-serialization-json)

367

val json = Json {

368

serializersModule = module

369

// Other JSON configuration...

370

}

371

372

@Serializable

373

data class Drawing(

374

val title: String,

375

@Contextual

376

val createdAt: LocalDateTime,

377

@Polymorphic

378

val shapes: List<Shape>

379

)

380

381

val drawing = Drawing(

382

title = "My Drawing",

383

createdAt = LocalDateTime.now(),

384

shapes = listOf(

385

Circle(5.0),

386

Rectangle(10.0, 20.0)

387

)

388

)

389

390

val jsonString = json.encodeToString(drawing)

391

val decoded = json.decodeFromString<Drawing>(jsonString)

392

```

393

394

## Best Practices

395

396

1. **Module Scope**: Create modules at application startup and reuse them

397

2. **Composition**: Use `include()` and `+` operator to compose modules from smaller, focused modules

398

3. **Default Providers**: Use default serializer/deserializer providers for handling unknown types gracefully

399

4. **Type Safety**: Prefer sealed classes for polymorphic hierarchies when possible

400

5. **Performance**: Cache module lookups in performance-critical code paths