Ktor JSON Content Negotiation via kotlinx.serialization support
npx @tessl/cli install tessl/maven-io-ktor--ktor-serialization-kotlinx-json@3.2.00
# Ktor JSON Serialization
1
2
Ktor JSON Content Negotiation via kotlinx.serialization support. This library provides JSON serialization and deserialization capabilities for Ktor applications using kotlinx.serialization, enabling automatic conversion between Kotlin objects and JSON format through the Content Negotiation plugin.
3
4
## Package Information
5
6
- **Package Name**: ktor-serialization-kotlinx-json
7
- **Package Type**: maven
8
- **Group ID**: io.ktor
9
- **Language**: Kotlin
10
- **Installation**: `implementation("io.ktor:ktor-serialization-kotlinx-json:3.2.0")`
11
12
## Core Imports
13
14
```kotlin
15
import io.ktor.serialization.kotlinx.json.*
16
```
17
18
For kotlinx.serialization JSON configuration:
19
20
```kotlin
21
import kotlinx.serialization.json.Json
22
```
23
24
For Content Negotiation setup:
25
26
```kotlin
27
import io.ktor.client.plugins.contentnegotiation.*
28
import io.ktor.server.plugins.contentnegotiation.*
29
```
30
31
For exception handling:
32
33
```kotlin
34
import io.ktor.serialization.JsonConvertException
35
import io.ktor.serialization.ContentConvertException
36
```
37
38
For extension provider:
39
40
```kotlin
41
import io.ktor.serialization.kotlinx.KotlinxSerializationExtensionProvider
42
```
43
44
For experimental converter:
45
46
```kotlin
47
import kotlinx.serialization.ExperimentalSerializationApi
48
```
49
50
## Basic Usage
51
52
### Server Configuration
53
54
```kotlin
55
import io.ktor.serialization.kotlinx.json.*
56
import io.ktor.server.application.*
57
import io.ktor.server.plugins.contentnegotiation.*
58
59
fun Application.configureSerialization() {
60
install(ContentNegotiation) {
61
json() // Uses DefaultJson configuration
62
}
63
}
64
```
65
66
### Client Configuration
67
68
```kotlin
69
import io.ktor.client.*
70
import io.ktor.client.plugins.contentnegotiation.*
71
import io.ktor.serialization.kotlinx.json.*
72
73
val client = HttpClient {
74
install(ContentNegotiation) {
75
json() // Uses DefaultJson configuration
76
}
77
}
78
```
79
80
### Custom JSON Configuration
81
82
```kotlin
83
import kotlinx.serialization.json.Json
84
85
install(ContentNegotiation) {
86
json(Json {
87
prettyPrint = true
88
isLenient = true
89
ignoreUnknownKeys = true
90
encodeDefaults = false
91
})
92
}
93
```
94
95
## Capabilities
96
97
### Standard JSON Serialization
98
99
Registers JSON content type with Content Negotiation plugin using kotlinx.serialization.
100
101
```kotlin { .api }
102
fun Configuration.json(
103
json: Json = DefaultJson,
104
contentType: ContentType = ContentType.Application.Json
105
)
106
```
107
108
**Parameters:**
109
- `json`: JSON format instance with configuration settings (optional, defaults to DefaultJson)
110
- `contentType`: Content type to register with the converter (optional, defaults to application/json)
111
112
### Experimental Streaming JSON Serialization
113
114
Registers JSON content type using experimental streaming JSON support for improved performance with large data.
115
116
```kotlin { .api }
117
@ExperimentalSerializationApi
118
fun Configuration.jsonIo(
119
json: Json = DefaultJson,
120
contentType: ContentType = ContentType.Application.Json
121
)
122
```
123
124
**Parameters:**
125
- `json`: JSON format instance (optional, defaults to DefaultJson)
126
- `contentType`: Content type to register (optional, defaults to application/json)
127
128
**Note:** This uses experimental kotlinx-io streaming for better memory efficiency with large JSON data.
129
130
### Flow and Sequence Support
131
132
Special handling for streaming collections using JSON arrays.
133
134
```kotlin { .api }
135
class KotlinxSerializationJsonExtensionProvider : KotlinxSerializationExtensionProvider {
136
override fun extension(format: SerialFormat): KotlinxSerializationExtension?
137
}
138
```
139
140
**Features:**
141
- Automatically serializes `Flow<T>` as JSON arrays with streaming
142
- Deserializes JSON arrays to `Sequence<T>` (JVM only)
143
- UTF-8 charset requirement for streaming operations
144
145
### Experimental JSON Converter
146
147
Direct converter class for advanced use cases requiring custom content negotiation handling.
148
149
```kotlin { .api }
150
@ExperimentalSerializationApi
151
class ExperimentalJsonConverter(private val format: Json) : ContentConverter {
152
override suspend fun serialize(
153
contentType: ContentType,
154
charset: Charset,
155
typeInfo: TypeInfo,
156
value: Any?
157
): OutgoingContent
158
159
override suspend fun deserialize(
160
charset: Charset,
161
typeInfo: TypeInfo,
162
content: ByteReadChannel
163
): Any?
164
}
165
```
166
167
**Usage Example:**
168
```kotlin
169
val converter = ExperimentalJsonConverter(Json {
170
prettyPrint = true
171
})
172
install(ContentNegotiation) {
173
register(ContentType.Application.Json, converter)
174
}
175
```
176
177
### Internal JSON Extensions
178
179
Internal implementation class that provides the actual Flow/Sequence serialization functionality.
180
181
```kotlin { .api }
182
internal class KotlinxSerializationJsonExtensions(private val format: Json) : KotlinxSerializationExtension {
183
override suspend fun serialize(
184
contentType: ContentType,
185
charset: Charset,
186
typeInfo: TypeInfo,
187
value: Any?
188
): OutgoingContent?
189
190
override suspend fun deserialize(
191
charset: Charset,
192
typeInfo: TypeInfo,
193
content: ByteReadChannel
194
): Any?
195
}
196
```
197
198
**Note:** This is an internal implementation class created by `KotlinxSerializationJsonExtensionProvider` and should not be used directly.
199
200
## Configuration and Types
201
202
### DefaultJson Configuration
203
204
Pre-configured JSON instance optimized for Ktor applications.
205
206
```kotlin { .api }
207
val DefaultJson: Json
208
```
209
210
**Configuration Settings:**
211
- `encodeDefaults = true` - Serializes properties with default values
212
- `isLenient = true` - Allows lenient JSON parsing
213
- `allowSpecialFloatingPointValues = true` - Allows NaN, Infinity, -Infinity
214
- `allowStructuredMapKeys = true` - Allows complex objects as map keys
215
- `prettyPrint = false` - Compact JSON output for efficiency
216
- `useArrayPolymorphism = false` - Uses object-based polymorphism
217
218
### Content Types
219
220
```kotlin { .api }
221
// From io.ktor.http package
222
ContentType.Application.Json // Standard application/json content type
223
```
224
225
### Required Imports for Types
226
227
```kotlin { .api }
228
// Core serialization imports
229
import io.ktor.serialization.*
230
import io.ktor.serialization.kotlinx.*
231
import io.ktor.http.*
232
import io.ktor.http.content.*
233
import io.ktor.util.reflect.*
234
import io.ktor.utils.io.*
235
import io.ktor.utils.io.charsets.*
236
import kotlinx.serialization.*
237
import kotlinx.serialization.json.*
238
import kotlinx.coroutines.flow.*
239
```
240
241
### Exception Types
242
243
```kotlin { .api }
244
// From io.ktor.serialization package
245
open class ContentConvertException(
246
message: String,
247
cause: Throwable? = null
248
) : Exception
249
250
class JsonConvertException(
251
message: String,
252
cause: Throwable? = null
253
) : ContentConvertException
254
```
255
256
- `ContentConvertException`: Base exception for content conversion errors
257
- `JsonConvertException`: Thrown when JSON conversion fails during serialization or deserialization
258
259
### Core Interface Types
260
261
```kotlin { .api }
262
// From io.ktor.serialization.kotlinx package
263
interface KotlinxSerializationExtensionProvider {
264
fun extension(format: SerialFormat): KotlinxSerializationExtension?
265
}
266
267
interface KotlinxSerializationExtension {
268
suspend fun serialize(
269
contentType: ContentType,
270
charset: Charset,
271
typeInfo: TypeInfo,
272
value: Any?
273
): OutgoingContent?
274
275
suspend fun deserialize(
276
charset: Charset,
277
typeInfo: TypeInfo,
278
content: ByteReadChannel
279
): Any?
280
}
281
282
// From io.ktor.serialization package
283
interface ContentConverter {
284
suspend fun serialize(
285
contentType: ContentType,
286
charset: Charset,
287
typeInfo: TypeInfo,
288
value: Any?
289
): OutgoingContent
290
291
suspend fun deserialize(
292
charset: Charset,
293
typeInfo: TypeInfo,
294
content: ByteReadChannel
295
): Any?
296
}
297
```
298
299
## Platform Support
300
301
### JVM Platform
302
- Full functionality including `Sequence<T>` deserialization
303
- Uses `Json.decodeToSequence(InputStream, KSerializer)` for efficient sequence parsing
304
- Sequence elements are parsed lazily during evaluation
305
- Requires UTF-8 charset for streaming operations
306
- Optimized streaming using `InputStream` for sequence parsing
307
308
### JavaScript Platform
309
- Standard JSON serialization and deserialization
310
- Sequence deserialization is not supported (returns null)
311
- Flow serialization supported
312
313
### Native Platforms (POSIX)
314
- Standard JSON serialization and deserialization
315
- Sequence deserialization is not supported (returns null)
316
- Flow serialization supported
317
318
### WebAssembly (WASM)
319
- Standard JSON serialization and deserialization
320
- Sequence deserialization is not supported (returns null)
321
- Flow serialization supported
322
323
## Usage Examples
324
325
### Serializing Data Classes
326
327
```kotlin
328
@Serializable
329
data class User(val id: Int, val name: String, val email: String)
330
331
// Server endpoint
332
post("/users") {
333
val user = call.receive<User>()
334
// Process user...
335
call.respond(user)
336
}
337
338
// Client request
339
val user = User(1, "John Doe", "john@example.com")
340
val response: User = client.post("http://localhost:8080/users") {
341
contentType(ContentType.Application.Json)
342
setBody(user)
343
}.body()
344
```
345
346
### Streaming Large Collections
347
348
```kotlin
349
// Server streaming response
350
get("/users/stream") {
351
val usersFlow: Flow<User> = getUsersAsFlow()
352
call.respond(usersFlow) // Automatically serialized as JSON array
353
}
354
355
// Client receiving stream (JVM only)
356
val users: Sequence<User> = client.get("http://localhost:8080/users/stream").body()
357
users.forEach { user ->
358
println("Received: $user")
359
}
360
```
361
362
### Custom JSON Configuration
363
364
```kotlin
365
install(ContentNegotiation) {
366
json(Json {
367
prettyPrint = true
368
isLenient = true
369
ignoreUnknownKeys = true
370
coerceInputValues = true
371
useAlternativeNames = false
372
namingStrategy = JsonNamingStrategy.SnakeCase
373
})
374
}
375
```
376
377
### Multiple Content Types
378
379
```kotlin
380
install(ContentNegotiation) {
381
json(DefaultJson, ContentType.Application.Json)
382
json(Json { prettyPrint = true }, ContentType("application", "vnd.api+json"))
383
}
384
```
385
386
## Error Handling
387
388
### Common Exceptions
389
390
- `JsonConvertException`: JSON parsing or serialization errors
391
- `SerializationException`: kotlinx.serialization errors (missing serializers, etc.)
392
- `ContentConvertException`: Base content conversion errors
393
394
### Error Handling Example
395
396
```kotlin
397
try {
398
val data = call.receive<MyDataClass>()
399
} catch (e: JsonConvertException) {
400
call.respond(HttpStatusCode.BadRequest, "Invalid JSON: ${e.message}")
401
} catch (e: SerializationException) {
402
call.respond(HttpStatusCode.BadRequest, "Serialization error: ${e.message}")
403
} catch (e: ContentConvertException) {
404
call.respond(HttpStatusCode.BadRequest, "Content conversion error: ${e.message}")
405
}
406
```