Ktor 1.6.4 Help

Content negotiation and serialization

The ContentNegotiation plugin (previously known as feature) serves two primary purposes:

  • Negotiating media types between the client and server. For this, it uses the Accept and Content-Type headers.

  • Serializing/deserializing the content in the specific format, which is provided by either the built-in kotlinx.serialization library or external ones, such as Gson and Jackson, amongst others.

Install ContentNegotiation

To install the ContentNegotiation plugin, pass it to the install function in the application initialization code. Depending on the way used to create a server, this can be the embeddedServer function call ...

import io.ktor.features.* // ... fun main() { embeddedServer(Netty, port = 8080) { install(ContentNegotiation) // ... }.start(wait = true) }

... or a specified module.

import io.ktor.features.* // ... fun Application.module() { install(ContentNegotiation) // ... }

Register a converter

To register a converter for a specified Content-Type, you need to call the register method. In the example below, two custom converters are registered to deserialize application/json and application/xml data:

install(ContentNegotiation) { register(ContentType.Application.Json, CustomJsonConverter()) register(ContentType.Application.Xml, CustomXmlConverter()) }

Built-in converters

Ktor provides the set of built-in converters for handing various content types without writing your own logic:

See a corresponding topic to learn how to install the required dependencies, register, and configure a converter.

Receive and send data

Create a data class

To deserialize received data into an object, you need to create a data class, for example:

data class Customer(val id: Int, val firstName: String, val lastName: String)

If you use kotlinx.serialization, make sure that this class has the @Serializable annotation:

import kotlinx.serialization.* @Serializable data class Customer(val id: Int, val firstName: String, val lastName: String)

Receive data

To receive and convert a content for a request, call the receive method that accepts a data class as a parameter:

post("/customer") { val customer = call.receive<Customer>() customerStorage.add(customer) call.respondText("Customer stored correctly", status = HttpStatusCode.Created) }

The Content-Type of the request will be used to choose a converter for processing the request. The example below shows a sample HTTP client request containing JSON data that will be converted to a Customer object on the server side:

POST http://0.0.0.0:8080/customer Content-Type: application/json { "id": 3, "firstName" : "Jet", "lastName": "Brains" }

You can find the full example here: json-kotlinx.

Send data

To pass a data object in a response, you can use the respond method:

get("/customer/{id}") { val id = call.parameters["id"] val customer: Customer = customerStorage.find { it.id == id!!.toInt() }!! call.respond(customer) }

In this case, Ktor uses the Accept header to choose the required converter. You can find the full example here: json-kotlinx.

Implement a custom converter

In Ktor, you can write your own converter for serializing/deserializing data. To do this, you need to implement the ContentConverter interface:

interface ContentConverter { suspend fun convertForSend(context: PipelineContext<Any, ApplicationCall>, contentType: ContentType, value: Any): Any? suspend fun convertForReceive(context: PipelineContext<ApplicationReceiveRequest, ApplicationCall>): Any? }

Take a look at the GsonConverter class as an implementation example.

Last modified: 07 September 2021