or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmessage-serialization.mdplugin-configuration.mdsession-management.mdwebsocket-connections.md

message-serialization.mddocs/

0

# Message Serialization

1

2

Content conversion support for serializing and deserializing objects to/from WebSocket frames with type safety.

3

4

## Required Imports

5

6

```kotlin

7

import io.ktor.client.plugins.websocket.*

8

import io.ktor.util.reflect.*

9

import io.ktor.serialization.*

10

import kotlinx.serialization.*

11

```

12

13

## Capabilities

14

15

### Serialization Functions

16

17

Type-safe functions for sending serialized data through WebSocket connections.

18

19

```kotlin { .api }

20

/**

21

* Serializes data to a frame and enqueues it using reified type information

22

* @param data The data object to serialize and send

23

* @throws WebsocketConverterNotFoundException if no contentConverter is configured

24

*/

25

suspend inline fun <reified T> DefaultClientWebSocketSession.sendSerialized(data: T)

26

27

/**

28

* Serializes data to a frame and enqueues it using explicit type information

29

* @param data The data object to serialize and send

30

* @param typeInfo Type information for the data object

31

* @throws WebsocketConverterNotFoundException if no contentConverter is configured

32

*/

33

suspend fun DefaultClientWebSocketSession.sendSerialized(data: Any?, typeInfo: TypeInfo)

34

```

35

36

**Usage Examples:**

37

38

```kotlin

39

// Configure client with content converter

40

val client = HttpClient {

41

install(WebSockets) {

42

contentConverter = KotlinxWebsocketSerializationConverter(Json)

43

}

44

}

45

46

@Serializable

47

data class Message(val text: String, val timestamp: Long)

48

49

client.webSocket("ws://example.com") {

50

// Send serialized object using reified type

51

val message = Message("Hello!", System.currentTimeMillis())

52

sendSerialized(message)

53

54

// Send serialized object using explicit type info

55

sendSerialized(message, typeInfo<Message>())

56

57

// Send different types

58

sendSerialized(42)

59

sendSerialized(listOf("a", "b", "c"))

60

sendSerialized(mapOf("key" to "value"))

61

}

62

```

63

64

### Deserialization Functions

65

66

Type-safe functions for receiving and deserializing data from WebSocket frames.

67

68

```kotlin { .api }

69

/**

70

* Dequeues a frame and deserializes it using reified type information

71

* @return Deserialized object of type T

72

* @throws WebsocketConverterNotFoundException if no contentConverter is configured

73

* @throws WebsocketDeserializeException if deserialization fails

74

*/

75

suspend inline fun <reified T> DefaultClientWebSocketSession.receiveDeserialized(): T

76

77

/**

78

* Dequeues a frame and deserializes it using explicit type information

79

* @param typeInfo Type information for deserialization target

80

* @return Deserialized object of type T

81

* @throws WebsocketConverterNotFoundException if no contentConverter is configured

82

* @throws WebsocketDeserializeException if deserialization fails

83

*/

84

suspend fun <T> DefaultClientWebSocketSession.receiveDeserialized(typeInfo: TypeInfo): T

85

```

86

87

**Usage Examples:**

88

89

```kotlin

90

@Serializable

91

data class Response(val status: String, val data: String)

92

93

client.webSocket("ws://example.com") {

94

// Send a request

95

sendSerialized(Message("ping", System.currentTimeMillis()))

96

97

// Receive and deserialize response

98

val response = receiveDeserialized<Response>()

99

println("Status: ${response.status}, Data: ${response.data}")

100

101

// Receive different types

102

val number = receiveDeserialized<Int>()

103

val list = receiveDeserialized<List<String>>()

104

val map = receiveDeserialized<Map<String, Any>>()

105

106

// Using explicit type info

107

val explicitResponse = receiveDeserialized<Response>(typeInfo<Response>())

108

}

109

```

110

111

### Content Converter Access

112

113

Access to the configured content converter for advanced usage.

114

115

```kotlin { .api }

116

/**

117

* Gets the WebSocket content converter from the client plugin configuration

118

* @return The configured WebsocketContentConverter or null if none configured

119

*/

120

val DefaultClientWebSocketSession.converter: WebsocketContentConverter?

121

```

122

123

**Usage Examples:**

124

125

```kotlin

126

client.webSocket("ws://example.com") {

127

val converter = converter

128

if (converter != null) {

129

println("Content converter available: ${converter::class.simpleName}")

130

131

// Can perform serialization/deserialization operations

132

sendSerialized("Hello World!")

133

} else {

134

println("No content converter configured")

135

136

// Must use raw frame sending

137

send("Hello World!")

138

}

139

}

140

```

141

142

## Content Converter Types

143

144

### WebSocket Content Converter Interface

145

146

Base interface for implementing custom content converters.

147

148

```kotlin { .api }

149

/**

150

* Interface for WebSocket content serialization/deserialization

151

*/

152

interface WebsocketContentConverter {

153

// Implementation details vary by concrete converter

154

}

155

```

156

157

### Exception Types

158

159

Exceptions thrown during serialization/deserialization operations.

160

161

```kotlin { .api }

162

/**

163

* Exception thrown when no suitable content converter is found

164

* @param message Error description

165

*/

166

class WebsocketConverterNotFoundException(message: String) : Exception(message)

167

168

/**

169

* Exception thrown when frame deserialization fails

170

* @param message Error description

171

* @param frame The WebSocket frame that failed to deserialize

172

*/

173

class WebsocketDeserializeException(message: String, val frame: Frame) : Exception(message)

174

```

175

176

## Serialization Examples

177

178

### JSON Serialization with Kotlinx.serialization

179

180

```kotlin

181

@Serializable

182

data class ChatMessage(

183

val user: String,

184

val message: String,

185

val timestamp: Long = System.currentTimeMillis()

186

)

187

188

@Serializable

189

data class ChatResponse(

190

val type: String,

191

val payload: ChatMessage

192

)

193

194

val client = HttpClient {

195

install(WebSockets) {

196

contentConverter = KotlinxWebsocketSerializationConverter(Json {

197

prettyPrint = true

198

ignoreUnknownKeys = true

199

})

200

}

201

}

202

203

client.webSocket("ws://chat.example.com") {

204

// Send chat message

205

sendSerialized(ChatMessage("user123", "Hello everyone!"))

206

207

// Receive responses

208

while (true) {

209

try {

210

val response = receiveDeserialized<ChatResponse>()

211

when (response.type) {

212

"message" -> println("${response.payload.user}: ${response.payload.message}")

213

"notification" -> println("System: ${response.payload.message}")

214

}

215

} catch (e: ClosedReceiveChannelException) {

216

break

217

}

218

}

219

}

220

```

221

222

### Custom Data Types

223

224

```kotlin

225

@Serializable

226

data class WebSocketCommand(

227

val action: String,

228

val parameters: Map<String, String> = emptyMap()

229

)

230

231

@Serializable

232

data class WebSocketEvent(

233

val event: String,

234

val data: JsonElement

235

)

236

237

client.webSocket("ws://api.example.com") {

238

// Send command

239

sendSerialized(WebSocketCommand(

240

action = "subscribe",

241

parameters = mapOf("channel" to "updates")

242

))

243

244

// Process events

245

for (frame in incoming) {

246

when (frame) {

247

is Frame.Text, is Frame.Binary -> {

248

try {

249

val event = receiveDeserialized<WebSocketEvent>()

250

handleEvent(event.event, event.data)

251

} catch (e: WebsocketDeserializeException) {

252

println("Failed to deserialize frame: ${e.message}")

253

// Handle raw frame if needed

254

if (frame is Frame.Text) {

255

println("Raw text: ${frame.readText()}")

256

}

257

}

258

}

259

is Frame.Close -> break

260

else -> {}

261

}

262

}

263

}

264

```

265

266

### Mixed Serialization and Raw Frames

267

268

```kotlin

269

client.webSocket("ws://example.com") {

270

// Send serialized object

271

sendSerialized(Message("Hello", 123))

272

273

// Send raw text frame

274

send("Raw text message")

275

276

// Send raw binary frame

277

send(byteArrayOf(1, 2, 3, 4))

278

279

// Receive and handle mixed content

280

for (frame in incoming) {

281

when (frame) {

282

is Frame.Text -> {

283

val text = frame.readText()

284

if (text.startsWith("{")) {

285

// Assume JSON, try to deserialize

286

try {

287

val message = receiveDeserialized<Message>()

288

println("Deserialized: $message")

289

} catch (e: WebsocketDeserializeException) {

290

println("Raw text: $text")

291

}

292

} else {

293

println("Raw text: $text")

294

}

295

}

296

is Frame.Binary -> {

297

try {

298

val data = receiveDeserialized<ByteArray>()

299

println("Deserialized binary: ${data.size} bytes")

300

} catch (e: WebsocketDeserializeException) {

301

println("Raw binary: ${frame.data.size} bytes")

302

}

303

}

304

is Frame.Close -> break

305

else -> {}

306

}

307

}

308

}

309

```

310

311

## Error Handling

312

313

### Converter Configuration Errors

314

315

```kotlin

316

client.webSocket("ws://example.com") {

317

try {

318

sendSerialized(Message("test", 123))

319

} catch (e: WebsocketConverterNotFoundException) {

320

println("No content converter configured: ${e.message}")

321

// Fall back to raw frame sending

322

send("""{"text":"test","id":123}""")

323

}

324

}

325

```

326

327

### Deserialization Errors

328

329

```kotlin

330

client.webSocket("ws://example.com") {

331

try {

332

val message = receiveDeserialized<Message>()

333

println("Received: $message")

334

} catch (e: WebsocketDeserializeException) {

335

println("Failed to deserialize frame: ${e.message}")

336

println("Frame type: ${e.frame::class.simpleName}")

337

338

// Handle raw frame content

339

when (val frame = e.frame) {

340

is Frame.Text -> println("Raw text: ${frame.readText()}")

341

is Frame.Binary -> println("Raw binary: ${frame.data.size} bytes")

342

}

343

}

344

}

345

```

346

347

### Type Safety

348

349

```kotlin

350

// Compile-time type safety

351

val message: Message = receiveDeserialized<Message>()

352

353

// Runtime type checking

354

inline fun <reified T> safeReceiveDeserialized(): T? {

355

return try {

356

receiveDeserialized<T>()

357

} catch (e: WebsocketDeserializeException) {

358

null

359

}

360

}

361

362

val maybeMessage = safeReceiveDeserialized<Message>()

363

if (maybeMessage != null) {

364

println("Successfully received: $maybeMessage")

365

}

366

```