Skip to main content

Serialization in Ktor

·3 mins

Previously, the API returned this response at the root path:

call.respondText("{\"message\":\"Hello World!\"}")

As we add new features, the API’s codebase will grow, and we will need to represent requests and responses using data classes to make the code more maintainable. Manually parsing incoming data and building a JSON string for every response is not ideal. Thankfully, there’s a solution: Serialization.

Serialization allows us to parse incoming request bodies and generate response bodies as classes seamlessly. Once set up, it works automatically without requiring manual intervention.

Let’s explore Content Negotiation and how to add JSON serialization in Ktor.

Content Negotiation #

Content Negotiation in a Ktor server facilitates negotiation of media types between the client and server by using the Accept and Content-Type headers. It handles serialization/deserialization in specific formats. Ktor supports the following formats out of the box: JSON, XML, CBOR, and ProtoBuf.

To enable content negotiation, add the following dependency to your build.gradle.kts file:

Add the below dependency to build.gradle.kts ;

implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")

Serialization #

Before using kotlinx.serialization converters, you need to add the Kotlin serialization plugin to your project.

Adding the Kotlin Serialization Plugin #

If you are using a version catalog, include the following in the plugins section of your version catalog file:

kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin-version" }

Then, apply the plugin in build.gradle.kts:

plugins {
    alias(libs.plugins.kotlin.serialization)
}

For our API, we will use JSON as the format for requests and responses.

JSON Serialization #

To enable JSON serialization, add the following artifact to your build.gradle.kts:

implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")

Now that we’ve added the necessary dependencies, we can configure the content negotiation plugin in our Ktor application to support JSON.

Adding Serialization to Ktor #

Create a new file called Serialization.kt and define the following function:

fun Application.configureSerialization() {
    install(ContentNegotiation) {
        json()
    }
}

Next, call this function in your module:

fun Application.module() {
    configureSerialization()
    //...
}

Updating the Root Path Response #

The setup is now complete! Let’s update the root path response in our API. Previously, it returned a hardcoded JSON string:

call.respondText("{\"message\":\"Hello World!\"}")

We can now replace this with a more structured approach using a map:

call.respond(
    mapOf("message" to "Hello, World!")
)

The response will be:

{
	"message": "Hello, World!"
}

Alternatively, you can create a class to represent the response model:

@Serializable
data class RootResponse(val message: String)

And use it like this:

call.respond(
    RootResponse("Hello, World!")
)

This will produce the same result.


Conclusion #

This was a short but essential step in developing an API. Serialization simplifies working with requests and responses, improving maintainability and scalability.

In the next steps, we’ll define request and response classes to facilitate seamless communication with the client.