or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

descriptors.mddocs/

0

# Serial Descriptors

1

2

Complete reference for SerialDescriptor and related APIs that describe the structure of serializable types in kotlinx.serialization-core-js.

3

4

## Core Interface

5

6

### SerialDescriptor

7

8

Primary interface for describing the structure of serializable types.

9

10

```kotlin

11

interface SerialDescriptor {

12

val serialName: String

13

val kind: SerialKind

14

val elementsCount: Int

15

16

fun getElementName(index: Int): String

17

fun getElementIndex(name: String): Int

18

fun isElementOptional(index: Int): Boolean

19

fun getElementDescriptor(index: Int): SerialDescriptor

20

fun getElementAnnotations(index: Int): List<Annotation>

21

fun isInline: Boolean

22

23

val annotations: List<Annotation>

24

val isNullable: Boolean

25

}

26

```

27

{ .api }

28

29

**Usage:**

30

31

```javascript

32

// Get descriptor from serializer

33

const userSerializer = User.serializer();

34

const descriptor = userSerializer.descriptor;

35

36

// Inspect structure

37

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

38

console.log(descriptor.kind); // StructureKind.CLASS

39

console.log(descriptor.elementsCount); // 3

40

41

// Iterate elements

42

for (let i = 0; i < descriptor.elementsCount; i++) {

43

const name = descriptor.getElementName(i);

44

const elementDesc = descriptor.getElementDescriptor(i);

45

const optional = descriptor.isElementOptional(i);

46

console.log(`${name}: ${elementDesc.serialName} (optional: ${optional})`);

47

}

48

```

49

50

## Serial Kinds

51

52

### SerialKind

53

54

Base sealed class for categorizing different types of serializable structures.

55

56

```kotlin

57

sealed class SerialKind {

58

final override fun toString(): String

59

}

60

```

61

{ .api }

62

63

### PrimitiveKind

64

65

Represents primitive types that cannot be decomposed further.

66

67

```kotlin

68

sealed class PrimitiveKind : SerialKind() {

69

object BOOLEAN : PrimitiveKind()

70

object BYTE : PrimitiveKind()

71

object CHAR : PrimitiveKind()

72

object SHORT : PrimitiveKind()

73

object INT : PrimitiveKind()

74

object LONG : PrimitiveKind()

75

object FLOAT : PrimitiveKind()

76

object DOUBLE : PrimitiveKind()

77

object STRING : PrimitiveKind()

78

}

79

```

80

{ .api }

81

82

**Usage:**

83

84

```javascript

85

// Check for primitive kinds

86

const stringDesc = String.serializer().descriptor;

87

console.log(stringDesc.kind === PrimitiveKind.STRING); // true

88

89

// Pattern matching on kind

90

function describePrimitive(descriptor) {

91

switch (descriptor.kind) {

92

case PrimitiveKind.BOOLEAN:

93

return "Boolean primitive";

94

case PrimitiveKind.STRING:

95

return "String primitive";

96

case PrimitiveKind.INT:

97

return "Integer primitive";

98

// ... other cases

99

default:

100

return "Not a primitive";

101

}

102

}

103

```

104

105

### StructureKind

106

107

Represents composite types with internal structure.

108

109

```kotlin

110

sealed class StructureKind : SerialKind() {

111

object CLASS : StructureKind()

112

object LIST : StructureKind()

113

object MAP : StructureKind()

114

object OBJECT : StructureKind()

115

}

116

```

117

{ .api }

118

119

**Usage:**

120

121

```javascript

122

// Check structure types

123

const userDesc = User.serializer().descriptor;

124

console.log(userDesc.kind === StructureKind.CLASS); // true

125

126

const listDesc = ListSerializer(String.serializer()).descriptor;

127

console.log(listDesc.kind === StructureKind.LIST); // true

128

129

const mapDesc = MapSerializer(String.serializer(), Int.serializer()).descriptor;

130

console.log(mapDesc.kind === StructureKind.MAP); // true

131

```

132

133

### PolymorphicKind

134

135

Represents types that support polymorphic serialization (Experimental).

136

137

```kotlin

138

@ExperimentalSerializationApi

139

sealed class PolymorphicKind : SerialKind() {

140

object SEALED : PolymorphicKind()

141

object OPEN : PolymorphicKind()

142

}

143

```

144

{ .api }

145

146

**Usage:**

147

148

```javascript

149

// Sealed class descriptor

150

const resultDesc = Result.serializer().descriptor;

151

console.log(resultDesc.kind === PolymorphicKind.SEALED); // true

152

153

// Open polymorphic descriptor

154

const shapeDesc = PolymorphicSerializer(Shape::class).descriptor;

155

console.log(shapeDesc.kind === PolymorphicKind.OPEN); // true

156

```

157

158

## Descriptor Factory Functions

159

160

### buildClassSerialDescriptor

161

162

Factory function for creating class descriptors with a builder DSL.

163

164

```kotlin

165

fun buildClassSerialDescriptor(

166

serialName: String,

167

typeParameters: Array<SerialDescriptor> = emptyArray(),

168

builderAction: ClassSerialDescriptorBuilder.() -> Unit = {}

169

): SerialDescriptor

170

```

171

{ .api }

172

173

**Usage:**

174

175

```javascript

176

const userDescriptor = buildClassSerialDescriptor("User") {

177

element("name", String.serializer().descriptor)

178

element("age", Int.serializer().descriptor, isOptional = true)

179

element("email", String.serializer().descriptor)

180

};

181

182

// With type parameters (for generic classes)

183

const pairDescriptor = buildClassSerialDescriptor("Pair", [

184

String.serializer().descriptor, // First type parameter

185

Int.serializer().descriptor // Second type parameter

186

]) {

187

element("first", getTypeParameter(0)) // Use first type parameter

188

element("second", getTypeParameter(1)) // Use second type parameter

189

};

190

```

191

192

### ClassSerialDescriptorBuilder

193

194

Builder class for constructing class descriptors.

195

196

```kotlin

197

class ClassSerialDescriptorBuilder(val serialName: String) {

198

fun element(

199

elementName: String,

200

descriptor: SerialDescriptor,

201

annotations: List<Annotation> = emptyList(),

202

isOptional: Boolean = false

203

)

204

205

fun getTypeParameter(index: Int): SerialDescriptor

206

}

207

```

208

{ .api }

209

210

**Usage:**

211

212

```javascript

213

// Advanced builder usage

214

const advancedDescriptor = buildClassSerialDescriptor("AdvancedClass") {

215

// Required element

216

element("id", String.serializer().descriptor)

217

218

// Optional element

219

element("description", String.serializer().descriptor, isOptional = true)

220

221

// Element with annotations

222

element("timestamp", Long.serializer().descriptor, [

223

SerialName("created_at")

224

])

225

226

// Nested structure

227

element("address", buildClassSerialDescriptor("Address") {

228

element("street", String.serializer().descriptor)

229

element("city", String.serializer().descriptor)

230

})

231

};

232

```

233

234

### PrimitiveSerialDescriptor

235

236

Factory for primitive descriptors.

237

238

```kotlin

239

fun PrimitiveSerialDescriptor(

240

serialName: String,

241

kind: PrimitiveKind

242

): SerialDescriptor

243

```

244

{ .api }

245

246

**Usage:**

247

248

```javascript

249

// Create custom primitive descriptor

250

const customStringDescriptor = PrimitiveSerialDescriptor(

251

"CustomString",

252

PrimitiveKind.STRING

253

);

254

255

// Use in serializer

256

class CustomStringSerializer {

257

constructor() {

258

this.descriptor = customStringDescriptor;

259

}

260

261

serialize(encoder, value) {

262

encoder.encodeString(value.toString().toUpperCase());

263

}

264

265

deserialize(decoder) {

266

return decoder.decodeString().toLowerCase();

267

}

268

}

269

```

270

271

### SerialDescriptor Factory (Wrapper)

272

273

Creates a descriptor that wraps another descriptor.

274

275

```kotlin

276

fun SerialDescriptor(

277

serialName: String,

278

original: SerialDescriptor

279

): SerialDescriptor

280

```

281

{ .api }

282

283

**Usage:**

284

285

```javascript

286

// Create wrapper descriptor with different name

287

const originalDesc = String.serializer().descriptor;

288

const wrappedDesc = SerialDescriptor("WrappedString", originalDesc);

289

290

console.log(wrappedDesc.serialName); // "WrappedString"

291

console.log(wrappedDesc.kind); // PrimitiveKind.STRING (from original)

292

```

293

294

### Collection Descriptors

295

296

Specialized factory functions for collection descriptors (Experimental).

297

298

```kotlin

299

@ExperimentalSerializationApi

300

fun listSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor

301

302

@ExperimentalSerializationApi

303

inline fun <reified T> listSerialDescriptor(): SerialDescriptor

304

305

@ExperimentalSerializationApi

306

fun mapSerialDescriptor(

307

keyDescriptor: SerialDescriptor,

308

valueDescriptor: SerialDescriptor

309

): SerialDescriptor

310

311

@ExperimentalSerializationApi

312

inline fun <reified K, reified V> mapSerialDescriptor(): SerialDescriptor

313

314

@ExperimentalSerializationApi

315

fun setSerialDescriptor(elementDescriptor: SerialDescriptor): SerialDescriptor

316

317

@ExperimentalSerializationApi

318

inline fun <reified T> setSerialDescriptor(): SerialDescriptor

319

```

320

{ .api }

321

322

**Usage:**

323

324

```javascript

325

// Collection descriptors

326

const stringListDesc = listSerialDescriptor(String.serializer().descriptor);

327

const reifiedListDesc = listSerialDescriptor<String>();

328

329

const stringIntMapDesc = mapSerialDescriptor(

330

String.serializer().descriptor,

331

Int.serializer().descriptor

332

);

333

const reifiedMapDesc = mapSerialDescriptor<String, Int>();

334

335

const stringSetDesc = setSerialDescriptor(String.serializer().descriptor);

336

const reifiedSetDesc = setSerialDescriptor<String>();

337

```

338

339

## Descriptor Utilities

340

341

### serialDescriptor Functions

342

343

Retrieve descriptors for types.

344

345

```kotlin

346

inline fun <reified T> serialDescriptor(): SerialDescriptor

347

348

fun serialDescriptor(type: KType): SerialDescriptor

349

```

350

{ .api }

351

352

**Usage:**

353

354

```javascript

355

// Get descriptor for reified type

356

const userDesc = serialDescriptor<User>();

357

const listDesc = serialDescriptor<List<String>>();

358

359

// Get descriptor for KType

360

const nullableStringType = typeOf<String?>();

361

const nullableStringDesc = serialDescriptor(nullableStringType);

362

```

363

364

### Nullable Descriptors

365

366

```kotlin

367

val SerialDescriptor.nullable: SerialDescriptor

368

369

@ExperimentalSerializationApi

370

val SerialDescriptor.nonNullOriginal: SerialDescriptor

371

```

372

{ .api }

373

374

**Usage:**

375

376

```javascript

377

const stringDesc = String.serializer().descriptor;

378

const nullableStringDesc = stringDesc.nullable;

379

380

console.log(stringDesc.isNullable); // false

381

console.log(nullableStringDesc.isNullable); // true

382

383

// Get original non-null descriptor

384

const originalDesc = nullableStringDesc.nonNullOriginal;

385

console.log(originalDesc === stringDesc); // true

386

```

387

388

### Iteration Utilities

389

390

```kotlin

391

val SerialDescriptor.elementDescriptors: Iterable<SerialDescriptor>

392

val SerialDescriptor.elementNames: Iterable<String>

393

```

394

{ .api }

395

396

**Usage:**

397

398

```javascript

399

const userDesc = User.serializer().descriptor;

400

401

// Iterate element names

402

for (const name of userDesc.elementNames) {

403

console.log(`Element: ${name}`);

404

}

405

406

// Iterate element descriptors

407

for (const [index, elementDesc] of userDesc.elementDescriptors.entries()) {

408

console.log(`Element ${index}: ${elementDesc.serialName}`);

409

}

410

411

// Combined iteration

412

const names = Array.from(userDesc.elementNames);

413

const descriptors = Array.from(userDesc.elementDescriptors);

414

415

names.forEach((name, index) => {

416

const desc = descriptors[index];

417

console.log(`${name}: ${desc.kind}`);

418

});

419

```

420

421

## Context-Aware Descriptors

422

423

### Captured KClass

424

425

Access to the original KClass for contextual and polymorphic types (Experimental).

426

427

```kotlin

428

@ExperimentalSerializationApi

429

val SerialDescriptor.capturedKClass: KClass<*>?

430

```

431

{ .api }

432

433

**Usage:**

434

435

```javascript

436

const polymorphicDesc = PolymorphicSerializer(Shape::class).descriptor;

437

const capturedClass = polymorphicDesc.capturedKClass;

438

console.log(capturedClass === Shape::class); // true

439

440

const contextualDesc = ContextualSerializer(Date::class).descriptor;

441

const dateClass = contextualDesc.capturedKClass;

442

console.log(dateClass === Date::class); // true

443

```

444

445

### Module Context Functions

446

447

Retrieve contextual information from SerializersModule (Experimental).

448

449

```kotlin

450

@ExperimentalSerializationApi

451

fun SerializersModule.getContextualDescriptor(

452

descriptor: SerialDescriptor

453

): SerialDescriptor?

454

455

@ExperimentalSerializationApi

456

fun SerializersModule.getPolymorphicDescriptors(

457

baseDescriptor: SerialDescriptor

458

): Collection<SerialDescriptor>

459

```

460

{ .api }

461

462

**Usage:**

463

464

```javascript

465

const module = SerializersModule {

466

contextual(Date::class, CustomDateSerializer)

467

polymorphic(Shape::class) {

468

subclass(Circle::class)

469

subclass(Rectangle::class)

470

}

471

};

472

473

// Get contextual descriptor

474

const dateDesc = Date::class.serializer().descriptor;

475

const contextualDesc = module.getContextualDescriptor(dateDesc);

476

477

// Get polymorphic descriptors

478

const shapeDesc = Shape::class.serializer().descriptor;

479

const subDescriptors = module.getPolymorphicDescriptors(shapeDesc);

480

console.log(subDescriptors.length); // 2 (Circle, Rectangle)

481

```

482

483

## Descriptor Inspection

484

485

### Complete Example

486

487

```javascript

488

function inspectDescriptor(descriptor, indent = 0) {

489

const spaces = ' '.repeat(indent);

490

491

console.log(`${spaces}Name: ${descriptor.serialName}`);

492

console.log(`${spaces}Kind: ${descriptor.kind}`);

493

console.log(`${spaces}Nullable: ${descriptor.isNullable}`);

494

console.log(`${spaces}Inline: ${descriptor.isInline}`);

495

console.log(`${spaces}Elements: ${descriptor.elementsCount}`);

496

497

if (descriptor.annotations.length > 0) {

498

console.log(`${spaces}Annotations: ${descriptor.annotations.map(a => a.constructor.name)}`);

499

}

500

501

// Inspect elements for structured types

502

if (descriptor.elementsCount > 0) {

503

for (let i = 0; i < descriptor.elementsCount; i++) {

504

const name = descriptor.getElementName(i);

505

const optional = descriptor.isElementOptional(i);

506

const elementDesc = descriptor.getElementDescriptor(i);

507

const annotations = descriptor.getElementAnnotations(i);

508

509

console.log(`${spaces} [${i}] ${name}${optional ? '?' : ''}:`);

510

if (annotations.length > 0) {

511

console.log(`${spaces} Annotations: ${annotations.map(a => a.constructor.name)}`);

512

}

513

514

// Recursive inspection for nested structures

515

if (elementDesc.elementsCount > 0) {

516

inspectDescriptor(elementDesc, indent + 4);

517

} else {

518

console.log(`${spaces} Type: ${elementDesc.serialName} (${elementDesc.kind})`);

519

}

520

}

521

}

522

}

523

524

// Usage

525

const userDescriptor = User.serializer().descriptor;

526

inspectDescriptor(userDescriptor);

527

```

528

529

### TypeScript Type Guards

530

531

```typescript

532

// Type guards for descriptor kinds

533

function isPrimitive(descriptor: SerialDescriptor): boolean {

534

return descriptor.kind instanceof PrimitiveKind;

535

}

536

537

function isStructured(descriptor: SerialDescriptor): boolean {

538

return descriptor.kind instanceof StructureKind;

539

}

540

541

function isPolymorphic(descriptor: SerialDescriptor): boolean {

542

return descriptor.kind instanceof PolymorphicKind;

543

}

544

545

// Specific structure checks

546

function isClass(descriptor: SerialDescriptor): boolean {

547

return descriptor.kind === StructureKind.CLASS;

548

}

549

550

function isList(descriptor: SerialDescriptor): boolean {

551

return descriptor.kind === StructureKind.LIST;

552

}

553

554

function isMap(descriptor: SerialDescriptor): boolean {

555

return descriptor.kind === StructureKind.MAP;

556

}

557

```

558

559

Serial descriptors provide complete introspection capabilities for serializable types, enabling format implementors and advanced users to understand and work with the structure of any serializable type at runtime.