Ktor: Problem with ktor-client and Kotlin Serialization Json Feature in a Multiplatform project

Created on 14 Apr 2020  路  3Comments  路  Source: ktorio/ktor

Ktor Version and Engine Used (client or server and name)
Version: 1.3.2
Engine: Client

Describe the bug
I'm using ktor-client in a Kotlin Multiplatform project, using kotlinx.serialization JsonFeature for both Android and iOS.

I'm trying to send a POST request with a body and I'm facing off the following error:

java.lang.IllegalStateException: Fail to send body. Content has type: class my.company.package.domain.user.DocumentAuthentication (Kotlin reflection is not available), but OutgoingContent expected.

The DocumentAuthentication is part of a sealed class:

sealed class UserAuthentication
    @Serializable data class EmailAuthentication(
        val email: String, val password: String
    ) : UserAuthentication()

    @Serializable data class DocumentAuthentication(
        @SerialName("document_number") val documentNumber: String, val password: String
    ) : UserAuthentication()

To Reproduce
Steps to reproduce the behavior:

  1. Write the following
  2. Run using browser/curl/etc
  3. See error

Expected behavior
So, I would like to understand if I'm doing something wrong and how can I fix that.

bug

Most helpful comment

Hi @e5l

By chance I figure out that the problem occurs just because I forgot to send the content type of body.

Wrong:

instance.post {
    url { path("authenticate") }
    body = userAuthentication
}

Right:

instance.post {
    url { path("authenticate") }
    header(HttpHeaders.ContentType, ContentType.Application.Json)
    body = userAuthentication
}

Sending the content type solves the problem.

I'm closing this issue.

All 3 comments

Hi @e5l

By chance I figure out that the problem occurs just because I forgot to send the content type of body.

Wrong:

instance.post {
    url { path("authenticate") }
    body = userAuthentication
}

Right:

instance.post {
    url { path("authenticate") }
    header(HttpHeaders.ContentType, ContentType.Application.Json)
    body = userAuthentication
}

Sending the content type solves the problem.

I'm closing this issue.

I'm facing the same issue, but setting ContentType header doesn't help =(

IllegalStateException Fail to send body. Content has type: class Credentials, but OutgoingContent expected.

Here's the sample code:

object ApiClient {
    val http: HttpClient = HttpClient(Js)

    init {
        http.config {
            install(JsonFeature) {
                serializer = KotlinxSerializer()
            }
        }
    }

    @Serializable
    data class Credentials(val username: String, val password: String)
    suspend fun login(creds: Credentials) {
        http.post<String>(url("/v1/login")) {
            header(HttpHeaders.ContentType, ContentType.Application.Json)
            body = creds
        }
    }
}

Hi @kam1sh

Take a look at this file: https://github.com/wellingtoncosta/todo-app-kotlin-multiplatform/blob/master/shared/src/commonMain/kotlin/io/github/wellingtoncosta/todoapp/data/api/TodoApi.kt

This is the full configuration / implementation of my networking layer using Ktor.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KennethanCeyer picture KennethanCeyer  路  4Comments

chrisjenx picture chrisjenx  路  4Comments

seanf picture seanf  路  3Comments

guenhter picture guenhter  路  4Comments

evgfilim1 picture evgfilim1  路  4Comments