or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builder-dsl.mdconfiguration.mdcore-operations.mdcustom-serializers.mddynamic-conversion.mdindex.mdjson-annotations.mdjson-element.md

configuration.mddocs/

0

# Configuration and Customization

1

2

Comprehensive configuration system for customizing JSON encoding/decoding behavior, naming strategies, and polymorphism handling. The JsonBuilder class provides extensive options to control how JSON serialization behaves.

3

4

## Capabilities

5

6

### JsonBuilder Configuration

7

8

Configure Json instances through the JsonBuilder class with extensive customization options.

9

10

```kotlin { .api }

11

/**

12

* Builder class for configuring Json instances

13

*/

14

class JsonBuilder {

15

/**

16

* Encode default property values (default: false)

17

*/

18

var encodeDefaults: Boolean

19

20

/**

21

* Explicitly encode/require null values (default: true)

22

*/

23

var explicitNulls: Boolean

24

25

/**

26

* Ignore unknown JSON properties during decoding (default: false)

27

*/

28

var ignoreUnknownKeys: Boolean

29

30

/**

31

* Coerce invalid input values to defaults (default: false)

32

*/

33

var coerceInputValues: Boolean

34

35

/**

36

* Enable pretty-printed JSON output (default: false)

37

*/

38

var prettyPrint: Boolean

39

40

/**

41

* Indentation string for pretty printing (default: " ")

42

*/

43

var prettyPrintIndent: String

44

45

/**

46

* Allow malformed JSON (unquoted keys/values) (default: false)

47

*/

48

var isLenient: Boolean

49

50

/**

51

* Allow NaN, Infinity values (default: false)

52

*/

53

var allowSpecialFloatingPointValues: Boolean

54

55

/**

56

* Allow complex objects as map keys (default: false)

57

*/

58

var allowStructuredMapKeys: Boolean

59

60

/**

61

* Allow trailing commas in objects/arrays (default: false)

62

*/

63

var allowTrailingComma: Boolean

64

65

/**

66

* Allow C-style comments in JSON (default: false)

67

*/

68

var allowComments: Boolean

69

70

/**

71

* Use @JsonNames alternative names (default: true)

72

*/

73

var useAlternativeNames: Boolean

74

75

/**

76

* Global property name transformation (default: null)

77

*/

78

var namingStrategy: JsonNamingStrategy?

79

80

/**

81

* Case-insensitive enum parsing (default: false)

82

*/

83

var decodeEnumsCaseInsensitive: Boolean

84

85

/**

86

* Property name for type discriminator (default: "type")

87

*/

88

var classDiscriminator: String

89

90

/**

91

* When to add discriminators (default: POLYMORPHIC)

92

*/

93

var classDiscriminatorMode: ClassDiscriminatorMode

94

95

/**

96

* Use legacy array-based polymorphism (default: false)

97

*/

98

var useArrayPolymorphism: Boolean

99

}

100

```

101

102

### Encoding/Decoding Behavior

103

104

Control how objects are serialized and deserialized.

105

106

**Usage Examples:**

107

108

```kotlin

109

@Serializable

110

data class User(

111

val name: String,

112

val age: Int = 25, // Default value

113

val email: String? = null,

114

val isActive: Boolean = true

115

)

116

117

// Default behavior

118

val defaultJson = Json.Default

119

val user = User("Alice")

120

val defaultResult = defaultJson.encodeToString(user)

121

// Result: {"name":"Alice"}

122

// Note: Default values and nulls are omitted

123

124

// Include default values

125

val includeDefaultsJson = Json {

126

encodeDefaults = true

127

}

128

val withDefaults = includeDefaultsJson.encodeToString(user)

129

// Result: {"name":"Alice","age":25,"email":null,"isActive":true}

130

131

// Handle null values explicitly

132

val explicitNullsJson = Json {

133

encodeDefaults = true

134

explicitNulls = true

135

}

136

val userWithEmail = User("Bob", email = "bob@example.com")

137

val withExplicitNulls = explicitNullsJson.encodeToString(userWithEmail)

138

// Result: {"name":"Bob","age":25,"email":"bob@example.com","isActive":true}

139

140

val noExplicitNullsJson = Json {

141

encodeDefaults = true

142

explicitNulls = false

143

}

144

val withoutExplicitNulls = noExplicitNullsJson.encodeToString(userWithEmail)

145

// Result: {"name":"Bob","age":25,"email":"bob@example.com","isActive":true}

146

// Note: Non-null email is still included

147

```

148

149

### Lenient Parsing

150

151

Handle malformed or non-standard JSON input.

152

153

```kotlin { .api }

154

/**

155

* Configuration modes for handling malformed JSON

156

*/

157

enum class ClassDiscriminatorMode {

158

NONE, // Never add class discriminators

159

POLYMORPHIC, // Add discriminators for polymorphic classes only

160

ALL_JSON_OBJECTS // Add discriminators for all JSON objects

161

}

162

```

163

164

**Usage Examples:**

165

166

```kotlin

167

// Strict JSON parsing (default)

168

val strictJson = Json.Default

169

170

// Lenient JSON parsing

171

val lenientJson = Json {

172

isLenient = true

173

ignoreUnknownKeys = true

174

coerceInputValues = true

175

allowSpecialFloatingPointValues = true

176

allowTrailingComma = true

177

allowComments = true

178

}

179

180

// Malformed JSON examples that work with lenient parsing

181

val malformedJson = """

182

{

183

// This is a comment

184

unquoted_key: "value",

185

"number": NaN,

186

"infinity": Infinity,

187

"trailing": "comma",

188

}

189

"""

190

191

try {

192

val parsed = lenientJson.decodeFromString<JsonElement>(malformedJson)

193

println("Lenient parsing succeeded")

194

} catch (e: JsonDecodingException) {

195

println("Lenient parsing failed: ${e.message}")

196

}

197

198

// Coercing invalid values

199

@Serializable

200

data class NumberData(val value: Int, val flag: Boolean)

201

202

val invalidDataJson = """{"value": "not_a_number", "flag": "yes"}"""

203

204

val coercingJson = Json {

205

coerceInputValues = true

206

}

207

208

val coercedData = coercingJson.decodeFromString<NumberData>(invalidDataJson)

209

// Result: NumberData(value = 0, flag = false) - invalid values coerced to defaults

210

```

211

212

### Pretty Printing

213

214

Format JSON output for human readability.

215

216

**Usage Examples:**

217

218

```kotlin

219

@Serializable

220

data class Product(

221

val id: String,

222

val name: String,

223

val categories: List<String>,

224

val metadata: Map<String, String>

225

)

226

227

val product = Product(

228

id = "PROD-001",

229

name = "Super Widget",

230

categories = listOf("electronics", "gadgets"),

231

metadata = mapOf("color" to "blue", "weight" to "1.5kg")

232

)

233

234

// Compact output (default)

235

val compactJson = Json.Default

236

val compact = compactJson.encodeToString(product)

237

// Result: {"id":"PROD-001","name":"Super Widget","categories":["electronics","gadgets"],"metadata":{"color":"blue","weight":"1.5kg"}}

238

239

// Pretty printed output

240

val prettyJson = Json {

241

prettyPrint = true

242

}

243

val pretty = prettyJson.encodeToString(product)

244

// Result:

245

// {

246

// "id": "PROD-001",

247

// "name": "Super Widget",

248

// "categories": [

249

// "electronics",

250

// "gadgets"

251

// ],

252

// "metadata": {

253

// "color": "blue",

254

// "weight": "1.5kg"

255

// }

256

// }

257

258

// Custom indentation

259

val customIndentJson = Json {

260

prettyPrint = true

261

prettyPrintIndent = " " // 2 spaces instead of 4

262

}

263

val customIndent = customIndentJson.encodeToString(product)

264

```

265

266

### Naming Strategies

267

268

Transform property names during serialization/deserialization.

269

270

```kotlin { .api }

271

/**

272

* Strategy for transforming property names

273

*/

274

interface JsonNamingStrategy {

275

/**

276

* Transform a serial name for JSON serialization

277

* @param descriptor Serial descriptor of the class

278

* @param elementIndex Index of the property in the class

279

* @param serialName Original property name

280

* @return Transformed property name for JSON

281

*/

282

fun serialNameForJson(descriptor: SerialDescriptor, elementIndex: Int, serialName: String): String

283

284

companion object {

285

/**

286

* Convert camelCase to snake_case

287

*/

288

val SnakeCase: JsonNamingStrategy

289

290

/**

291

* Convert camelCase to kebab-case

292

*/

293

val KebabCase: JsonNamingStrategy

294

}

295

}

296

```

297

298

**Usage Examples:**

299

300

```kotlin

301

@Serializable

302

data class ApiResponse(

303

val userId: Int,

304

val firstName: String,

305

val lastName: String,

306

val emailAddress: String,

307

val isActiveUser: Boolean

308

)

309

310

val response = ApiResponse(

311

userId = 123,

312

firstName = "Alice",

313

lastName = "Smith",

314

emailAddress = "alice@example.com",

315

isActiveUser = true

316

)

317

318

// Default naming (camelCase)

319

val defaultNaming = Json.Default

320

val camelCase = defaultNaming.encodeToString(response)

321

// Result: {"userId":123,"firstName":"Alice","lastName":"Smith","emailAddress":"alice@example.com","isActiveUser":true}

322

323

// Snake case naming

324

val snakeCaseJson = Json {

325

namingStrategy = JsonNamingStrategy.SnakeCase

326

}

327

val snakeCase = snakeCaseJson.encodeToString(response)

328

// Result: {"user_id":123,"first_name":"Alice","last_name":"Smith","email_address":"alice@example.com","is_active_user":true}

329

330

// Kebab case naming

331

val kebabCaseJson = Json {

332

namingStrategy = JsonNamingStrategy.KebabCase

333

}

334

val kebabCase = kebabCaseJson.encodeToString(response)

335

// Result: {"user-id":123,"first-name":"Alice","last-name":"Smith","email-address":"alice@example.com","is-active-user":true}

336

337

// Custom naming strategy

338

val customNamingJson = Json {

339

namingStrategy = object : JsonNamingStrategy {

340

override fun serialNameForJson(descriptor: SerialDescriptor, elementIndex: Int, serialName: String): String {

341

return serialName.uppercase() // Convert all property names to uppercase

342

}

343

}

344

}

345

val uppercase = customNamingJson.encodeToString(response)

346

// Result: {"USERID":123,"FIRSTNAME":"Alice","LASTNAME":"Smith","EMAILADDRESS":"alice@example.com","ISACTIVEUSER":true}

347

```

348

349

### Alternative Names

350

351

Support multiple property names during deserialization.

352

353

**Usage Examples:**

354

355

```kotlin

356

@Serializable

357

data class User(

358

@JsonNames("user_id", "id")

359

val userId: Int,

360

361

@JsonNames("user_name", "username", "login")

362

val name: String,

363

364

@JsonNames("email_address", "mail")

365

val email: String

366

)

367

368

val flexibleJson = Json {

369

useAlternativeNames = true // Default is true

370

}

371

372

// All these JSON variations can be deserialized to the same User object

373

val json1 = """{"userId":1,"name":"Alice","email":"alice@example.com"}"""

374

val json2 = """{"user_id":1,"user_name":"Alice","email_address":"alice@example.com"}"""

375

val json3 = """{"id":1,"username":"Alice","mail":"alice@example.com"}"""

376

val json4 = """{"user_id":1,"login":"Alice","email":"alice@example.com"}"""

377

378

val user1 = flexibleJson.decodeFromString<User>(json1)

379

val user2 = flexibleJson.decodeFromString<User>(json2)

380

val user3 = flexibleJson.decodeFromString<User>(json3)

381

val user4 = flexibleJson.decodeFromString<User>(json4)

382

383

// All result in the same User object

384

assert(user1 == user2)

385

assert(user2 == user3)

386

assert(user3 == user4)

387

```

388

389

### Enum Handling

390

391

Configure enum serialization and deserialization behavior.

392

393

**Usage Examples:**

394

395

```kotlin

396

@Serializable

397

enum class Status { ACTIVE, INACTIVE, PENDING }

398

399

@Serializable

400

data class Record(val id: Int, val status: Status)

401

402

// Case-sensitive enum parsing (default)

403

val strictEnumJson = Json.Default

404

405

// Case-insensitive enum parsing

406

val lenientEnumJson = Json {

407

decodeEnumsCaseInsensitive = true

408

}

409

410

// These will work with case-insensitive parsing

411

val variations = listOf(

412

"""{"id":1,"status":"ACTIVE"}""",

413

"""{"id":1,"status":"active"}""",

414

"""{"id":1,"status":"Active"}""",

415

"""{"id":1,"status":"AcTiVe"}"""

416

)

417

418

variations.forEach { json ->

419

try {

420

val record = lenientEnumJson.decodeFromString<Record>(json)

421

println("Parsed: $record")

422

} catch (e: JsonDecodingException) {

423

println("Failed to parse: $json")

424

}

425

}

426

```

427

428

### Polymorphism Configuration

429

430

Control polymorphic serialization behavior.

431

432

**Usage Examples:**

433

434

```kotlin

435

@Serializable

436

abstract class Animal {

437

abstract val name: String

438

}

439

440

@Serializable

441

@SerialName("dog")

442

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

443

444

@Serializable

445

@SerialName("cat")

446

data class Cat(override val name: String, val lives: Int) : Animal()

447

448

// Default polymorphic configuration

449

val defaultPolymorphicJson = Json {

450

classDiscriminator = "type" // Default

451

classDiscriminatorMode = ClassDiscriminatorMode.POLYMORPHIC // Default

452

}

453

454

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

455

val polymorphicResult = defaultPolymorphicJson.encodeToString<Animal>(dog)

456

// Result: {"type":"dog","name":"Buddy","breed":"Golden Retriever"}

457

458

// Custom discriminator property name

459

val customDiscriminatorJson = Json {

460

classDiscriminator = "objectType"

461

}

462

463

val customResult = customDiscriminatorJson.encodeToString<Animal>(dog)

464

// Result: {"objectType":"dog","name":"Buddy","breed":"Golden Retriever"}

465

466

// Array-based polymorphism (legacy)

467

val arrayPolymorphicJson = Json {

468

useArrayPolymorphism = true

469

}

470

471

val arrayResult = arrayPolymorphicJson.encodeToString<Animal>(dog)

472

// Result: ["dog",{"name":"Buddy","breed":"Golden Retriever"}]

473

474

// Discriminator modes

475

val allObjectsJson = Json {

476

classDiscriminatorMode = ClassDiscriminatorMode.ALL_JSON_OBJECTS

477

classDiscriminator = "className"

478

}

479

480

@Serializable

481

data class SimpleData(val value: String)

482

483

val simpleData = SimpleData("test")

484

val withDiscriminator = allObjectsJson.encodeToString(simpleData)

485

// Result: {"className":"SimpleData","value":"test"}

486

```