First of all, let me tell you that I enjoy using the Kotlin SDK and it’s great that there’s a dedicated SDK and not just Java. What I am having issues with is serialization and especially KotlinSerializationJsonSerializer. I’ve noticed that the current implementation limitations are due to this issue in kotlin.serialization. As you can see it’s already been resolved for some time. So I was wondering are there any plans to fix it now that’s there’s no obstruction anymore?
It is important to provide a fix, since it’s quite complicated to work with SQL++ API as a mandatory serialization is applied for all QueryParameters. The query() provides the serializer parameter, but there’s no transcoding. Gladly, for KV it’s not so bad due to Content.json, but often it’s not reasonable to use KV-only.
Thanks for the kind words about the Kotlin SDK. It’s a labor of love, and it’s great to hear people are using it.
Couchbase Kotlin SDK 1.5 will require Kotlin 1.9 or later, so we will finally be able to take advantage of the improved performance and stability of the kotlinx.serialization API. The release date for Couchbase Kotlin SDK 1.5 is to be determined, but I would be surprised if it’s more than a few months away.
Thank you for reporting the issues with KotlinxSerializationJsonSerializer and query parameters, which we’re now tracking as KCBC-179. We might need to design a new API for specifying query parameters in a way that preserves the type information required by kotlinx.serialization.
In the meantime, a potential workaround us to use JacksonJsonSerializer for serializing the query parameters, and KotlinxSerializationJsonSerializer for deserializing the result rows:
val kotlinxSerializer = KotlinxSerializationJsonSerializer()
val jacksonSerializer = JacksonJsonSerializer(
JsonMapper.builder()
.addModule(KotlinModule.Builder().build())
.build()
)
@Serializable
data class MyThing(val name: String)
val cluster = Cluster.connect("couchbase://127.0.0.1", "Administrator", "password") {
jsonSerializer = kotlinxSerializer
}
try {
runBlocking {
val queryResult = cluster.query(
"select RAW ?",
parameters = QueryParameters.positional(listOf(mapOf("name" to "foo"))),
serializer = jacksonSerializer,
).execute()
queryResult.rows.forEach {
println(it.contentAs<MyThing>(serializer = kotlinxSerializer))
}
}
} finally {
runBlocking { cluster.disconnect() }
}
Specifying serializers like this for every query is inconvenient, but hopefully it will tide you over until we deliver a real solution.
Thanks for the quick response and the suggested workaround. The API for KCBC-179 looks great, can’t wait for it to be merged! Do I understand correctly that since the complete type info will be preserved, I can write my own JsonSerializer for kotlinx.serialization that would be able to handle nullable types?
Do I understand correctly that since the complete type info will be preserved, I can write my own JsonSerializer for kotlinx.serialization that would be able to handle nullable types?
The fix for KCBC-179 won’t resolve the nullability issue; it will just capture enough information to work with the existing kotlinx.serialization integration. In other words, it won’t be perfect right away, but at least it won’t explode anymore.
I do not believe full support for nullable types is possible without modifying the SDK source code. The TypeRef class will need to create a KSerializer<T> or capture enough information to create one later.
However, if you try this and are successful, I’d definitely like to hear about it!
The upcoming patch release of the Couchbase Kotlin SDK fixes KCBC-180, which prevented KotlinSerializationJsonSerializer from serializing and deserializing nulls at the document root.