Home > other >  java.lang.IllegalStateException: Fail to serialize body. Content has type: class java.util.Collectio
java.lang.IllegalStateException: Fail to serialize body. Content has type: class java.util.Collectio

Time:12-24

I'm attempting to deserialize a JSON list of strings into the body of a ktor POST request for testing. However I get the following error:

java.lang.IllegalStateException: Fail to serialize body. Content has type: class java.util.Collections$SingletonList, but OutgoingContent expected.
If you expect serialized body, please check that you have installed the corresponding feature(like `Json`) and set `Content-Type` header.)

Any suggestions?

Here is my test setup:

import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import javax.inject.Singleton


@Provides
@Singleton
fun provideKtorHttpClient(
    mockEngine: MockEngine
): HttpClient {
    return HttpClient(mockEngine) {
        install(JsonFeature) {
            serializer = KotlinxSerializer()
            acceptContentTypes = listOf(
                ContentType.parse("application/vnd.any.response json"),
                ContentType.parse("application/json")
            )
        }
    }
}


@Provides
@Singleton
fun mockEngine(): MockEngine {
    val mockEngine = MockEngine { request ->

        when {
            request.url.fullPath.endsWith("lorem") -> {
                val body = request.body as TextContent
                val words: List<String> = Json.decodeFromString(body.text)
                when (words[0]) {
                    "Foo" -> respond(
                        content = ByteReadChannel("Ok"),
                        status = HttpStatusCode.OK,
                        headers = headersOf(HttpHeaders.ContentType, "application/json")
                    )
                    else ->
                        respond(
                            content = ByteReadChannel("Not found"),
                            status = HttpStatusCode.NotFound,
                            headers = headersOf(HttpHeaders.ContentType, "application/json")
                        )
                }
            }
        }
    }
}

class MyApi @Inject constructor(
    private val httpClient: HttpClient
) {
    suspend fun postData(words: List<String>): Either<Exception, String> = Either.catch {
        httpClient.post<String>("https://foo.bar/api/lorem") {
            body = words
        }
    }
}

@Test
fun testApiOk() = runBlocking {
    val myApi = MyApi(httpClient, networkingConstants)
    runBlocking {
        val result = myApi.postData(listOf("Foo"))
        assertTrue(result.isRight())
    }
}

CodePudding user response:

Just add the Content-Type header to the request builder so the JsonFeature will serialize the body.

suspend fun postData(words: List<String>): Either<Exception, String> = Either.catch {
    httpClient.post<String>("https://foo.bar/api/lorem") {
        body = words
        contentType(ContentType.Application.Json)
    }
}
  • Related