Reputation: 597
I know there are several posts about it, from people that initially didn't know how to configure the ContentNegotiation either on server or client. But I have read all the docs and I have configured as per documentation both the ContentNegotiation plugin and the Serialization.
The code actually works and can deserialize to a data class my request (sent from curl, with content-type set to application/json
) and send a HTTP 200 response with the data.
However there is still a trace in the logs:
No Default Transformations found for class io.ktor.utils.io.ByteBufferChannel
and expected type TypeInfo(type=class com.example.User,
reifiedType=class com.example.User, kotlinType=com.example.User)
for call /user
Here is the full application (server side, I'm calling from curl for the client). I created it with the https://start.ktor.io/ enabling ContentNegotiation and Serialization with kotlinx :
package com.example
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
@Serializable
data class User(val firstName: String, val lastName: String)
@Suppress("unused")
fun Application.module() {
install(ContentNegotiation) {
json()
}
routing {
post("/user") {
val user = call.receive<User>()
call.respond(user)
}
}
}
and my build.gradle.kts
is:
val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project
plugins {
kotlin("jvm") version "1.8.22"
id("io.ktor.plugin") version "2.3.1"
id("org.jetbrains.kotlin.plugin.serialization") version "1.8.22"
}
group = "com.example"
version = "0.0.1"
application {
mainClass.set("io.ktor.server.netty.EngineMain")
val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
}
repositories {
mavenCentral()
}
dependencies {
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm:$ktor_version")
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
I call this application from curl
:
curl --location 'http://0.0.0.0:8080/user' \
--header 'Content-Type: application/json' \
--data '{
"firstName": "John",
"lastName": "Smith"
}'
And the result is expected:
{"firstName":"John","lastName":"Smith"}
Why is it still complaining about not being able to transform? It apparently can and return the correct result.
Upvotes: 1
Views: 704
Reputation: 21
I just started a project with ktor and I also ran into this message. It's quite easy to reproduce by creating a new project with sample code using the IntelliJ plugin.
Since this is my first project with ktor I'm far from an expert but as far as I can tell this is an innocent message informing us what is happening under the hood. Trace messages give the most fine grained information. If there was something out of the ordinary a warning should be logged or at least a message at debug level saying something along the line of "This could be problem, you might want to do X"
It's just telling us that no transformation took place. From what I can tell from the code, some received body (and parameter?) types may need transformation before they're passed along the pipeline, where deserialization takes place.
Some examples of what will be transformed are urlencoded and multipart payloads.
In my opinion the log message should be reworded because to me it also implied I was doing something wrong with serialization and it was falling back to some kind of compatibility mode.
As an alternative, maybe debug should be the default log level.
Upvotes: 0