Using kotlinx.serialization in Ktor
Post describing how I used kotlinx.serialization in my Ktor project
In my previous post, we created a simple Ktor server and deployed it to Heroku. Now let’s build on the same project you can check the GitHub for the project here
If you are creating a Ktor Server serving REST endpoints one thing you will definitely need is serializing and deserializing the request/response data. Through my experience working in Android development, I am familiar with libraries like Gson and Jackson but I thought of exploring kotlinx.serialization for my side project because of its Kotlin Multiplatform support. If you’re a Kotlin enthusiast, you’ll love its elegance.
NOTE: kotlinx.serialization requires Kotlin compiler 1.4.0 or higher
Adding dependencies
Update the build.gradle.kts
with dependencies for Content Negotiation and serialization
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
Quick note on Content Negotiation, in the Ktor project it serves two purposes negotiating the media types between client/server and serializing/deserializing the content in a specific format. Ktor supports JSON, XML, CBOR, and ProtoBuf. We will be using JSON
You will also need to add the below plugin to your build.gradle.kts
file otherwise the annotation @Serializable
will be not recognized (you might see a warning if you don’t include this). Plugins for my project look like below, make sure to use relevant versions here.
plugins {
kotlin("jvm") version "1.9.10"
id("io.ktor.plugin") version "2.3.5"
id("org.jetbrains.kotlin.plugin.serialization") version "1.8.0"
}
Run gradle sync and everything should build.
Add models
Now we can add the model classes which will represent request/response data. I added two simple login flow model classes which look like this:
@Serializable
data class LoginRequestData(
val email: String,
val password: String
)
@Serializable
data class LoginResponseData(
val id: String,
val email: String,
)
These are added to a new file LoginModel
which is created in a new package model
Add Serialization Plugin
To start using kotlinx.serialization as a way to serialize/deserialize in our application we need to configure the plugin and add it to the application. Create a new file under plugin
package named Serialization
and add below to it:
fun Application.configureSerialization() {
install(ContentNegotiation) {
json(Json {
namingStrategy = JsonNamingStrategy.SnakeCase
})
}
}
Using JsonNamigStrategy.SnakeCase
is required if you want your underscores in JSON to be converted to snake case Kotlin data fields. As an example, date_of_birth: "1 Jan 1990"
in JSON will be dateOfBirth = "1 Jan 1990
Update your Application
to include this configuration
fun Application.module() {
configureSerialization()
configureRouting()
}
Testing time!!!
Now to quickly test if everything we did so far is working as expected or not make a POST request using Postman and verify.
We can also add a test for this by providing request data in JSON format as String and verifying that the response has id, email, and expected email value. The final test looks like this:
@Test
fun testLoginRequest() = testApplication {
val requestData = "{\n" +
" \"email\": \"test@gmail.com\",\n" +
" \"password\": \"12345678\"\n" +
"}"
val response = client.post("/login") {
contentType(ContentType.Application.Json)
setBody(requestData)
}
val responseBody = response.bodyAsText()
assertEquals(HttpStatusCode.OK, response.status)
assertNotNull(responseBody)
assertEquals(true, responseBody.contains("id"))
assertEquals(true, responseBody.contains("email"))
assertEquals(true, responseBody.contains("test@gmail.com"))
}
And we are done
My experience so far with kotlinx.serialization library has been great, I struggled to understand a few things, especially working with date time, and timezones (topic for next post) but eventually it’s easy to use. Thanks for reading this post, please share your comments, feedback, or your experience using Ktor.
I’ll continue to add to the project so feel free to watch this project