How do we configure serialization now with Ktor 2.0 on an Android client? This example for previous...
n
How do we configure serialization now with Ktor 2.0 on an Android client? This example for previous versions is deprecated and no longer works:
Copy code
client = HttpClient(Android) {
    install(JsonFeature) {
      serializer = KotlinxSerializer()
    }
}
The migration guide says to use the content negotiation plugin, but there are no examples of how to do this on Android that I can see.
d
Copy code
install(ContentNegotiation) { json() }
a
https://ktor.io/docs/serialization-client.html. this link has more detailed info, but you will need to follow format by @Dominaezzz.
n
Thanks, I see it now. I was also missing the dependency of
implementation("io.ktor:ktor-client-content-negotiation:$ktor_version")
I have serialization configured and there are no errors at build time, but when I run the app I get this error:
java.lang.IllegalStateException: No request transformation found:
thrown by this function:
Copy code
val response = client
  .post(HttpRoutes.LOGIN) {
    contentType(ContentType.Application.Json)
    setBody(loginRequest) // <- this line fails
  }
where
client : HttpClient
and
loginRequest
is
Copy code
@Serializable
data class LoginRequest(
  val email : String,
  val password : String
)
Am I not serializing the request correctly? Apparently not - the
setBody
call needs to instead be:
Copy code
setBody(Json.encodeToString(LoginRequest.serializer(), loginRequest))
So finally I would like to parse the response from the above POST request, using the
.body()
method:
Copy code
val userData : UserData = client
  .post(HttpRoutes.LOGIN) {
    contentType(ContentType.Application.Json)
    setBody(Json.encodeToString(LoginRequest.serializer(), loginRequest))
  }
  .body<UserData>()
This fails with the error:
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel -> class UserData
Why is it ByteBufferChannel and not a Json or text?
d
Can I see the configuration?
n
Copy code
fun create() : AuthService {
  return AuthServiceImpl(
    client = HttpClient(Android) {
      install(ContentNegotiation) {
        json()
      }
    }
  )
}
I’m thinking it may be an issue with my Ktor server. The
Content-Type
header is indeed
text/plain; charset=UTF-8
where I would have expected
application/json
. My server is running Ktor 2.0, and the response is sent using
Copy code
call.respond(result.statusCode, ResponseSerializer.encodeToString(result))
The docs say that content-type gets set automatically by serialization. Is it possible to set this manually or override the default?
The solution is apparently to cast the output from
.body()
explicitly, instead of just passing a type argument as the docs suggest. This works:
Copy code
val userData = Json.decodeFromString(
  client
    .post(HttpRoutes.LOGIN) {
      contentType(ContentType.Application.Json)
      setBody(Json.encodeToString(LoginRequest.serializer(), loginRequest))
    }
    .body()
) as UserData
This does not work:
Copy code
val userData : UserData = client
  .post(HttpRoutes.LOGIN) {
    contentType(ContentType.Application.Json)
    setBody(Json.encodeToString(LoginRequest.serializer(), loginRequest))
  }
  .body<UserData>()
I’m not really sure what the difference is, but
body()
is not able to either parse or cast the Json string from the response.
c
hey, did you fix that?
n
beware of syntax correct is
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
})
}
not install(ContentNegotiation) { Json { prettyPrint = true isLenient = true } }
1673 Views