so i have been experimenting with kotlinx.serilaiz...
# ktor
n
so i have been experimenting with kotlinx.serilaizazion for ktor-client . https://gist.github.com/NikkyAI/2e2891ccf67d423c523311f0b43ca57b it seems to be a mess currently, registering classes for read/write mapper seems to make using generics like `List`s impossible this could work if the ktor-client Framework could pass reified types down instead of assuming the Json serializer can handle Any PS: sorry for the many edits, slack keeps cutting out and not actually saving
e
I would return just plain text from call and do serialization work somewhere else
n
thats what i ended up doing for the List at least
d
I haven’t tried myself yet. I think I’m going to try so I can help more. Have you used the
@Serializable
annotation? https://github.com/Kotlin/kotlinx.serialization I would expect that to work out of the box. But since I haven’t tried yet, maybe it is not the case. Also there is a #serialization channel for doubts/feedback (if the issue is not related to ktor directly)
n
yes, i can deserialize it by hand just fine when i turn it into a String first I tried to make my own kotlinXSerializer for jsonFeature and it seems like
fun write(data: Any): OutgoingContent
is just not enough type info 😛
yes i know of the channel but this is relatede ktor-client JsonFeature for it, i think
👍 1
d
I have used
kotlinx.serialization
alone but not the client feature. Looking at the code, I guess that makes sense.
@e5l
I guess, you can register not your own serializer, but your own serialization feature that gets type information. Though can you use
data::class
to get a class instance and then get the type to serialize?
n
i think the issue might be that lists are only supported when nested within a serializable class ? in that case it would be a question for #serialization
That class doesn’t help? I guess it was created for that topic.
n
it seems to e only available for parsing json
d
Also, are you sending
[]
directly? without being wrapped by an object? That’s valid json?
n
it was for just about every other library i used, including jackson
d
Can’t you wrap the array in an object, and then strip the initial part and the tailing as a dirty, dirty workaround?
n
i could probably make a wrapper and some String templating to work around it
d
I’m suggesting it so you are not blocked, but I think that it is something we should look at. So if you can, I would add an issue with the problem here: https://github.com/ktorio/ktor/issues
n
solution that works:
@Serializable class ListWrapper(val list: List<AddonFile>)
Copy code
val content = client.get<String>(url)
return json.parse<ListWrapper>("{ \"list\": $content }").list
👍 2
e
Kotlinx.serializer feature supports only type mappers from the feature configuration for now.
n
is that being worked on and a hard problem or do you think it would be worth giving it a try to adapt a custom JsonFeature ?
e
It’s easy task for jvm and quite hard for ios. If you use jvm only client consider using
gson
serializer.
n
either way i think the fact that RequestPipeline is effectively untyped is the root cause here.. i assume changing that would break on native platforms though unless you made heavy use of inline reified
d
can’t you use a KClass instance to get a serializer/deserializer? edit: I used
clazz.serializer
here and it worked https://github.com/mmo-poc/mmo-poc/blob/2d7d82d9bec0ef95c93bb90447caf20e3a0d6038/mmo/common/src/mmo/protocol/serial.kt#L17 but maybe I’m missing something
n
i think you are right.. i was mixing up multiple issues and getting confused
and no that does not work

https://i.imgur.com/oIooQaC.png

d
you need type information
1 sec
n
which the Pipeline does not contain as far as i can see
and thats why the current implementation has to register them all by class and then looks up the mappers
d
have you tried to do some casts?
I have tried:
Copy code
fun <T : Any> serializePacket(obj: T, clazz: KClass<T>): String {
    //return JSON.stringify(Packet(clazz.serialName, JSON.stringify(clazz.serializer(), obj)))
    return serializePacket(obj)
}

fun serializePacket(obj: Any): String {
    val clazz: KClass<*> = obj::class
    val serializer = clazz.serializer()
    @Suppress("UNCHECKED_CAST")
    return JSON.stringify(Packet(clazz.serialName, JSON.stringify(serializer as SerializationStrategy<Any>, obj)))
}
it compiles at least. (Though not testest)
edit: tested. It works. No reified required. Just an instance + ::class + .serializer and some unsafe casts
n
where does SerializationStrategy come from ?
d
kotlinx-serialization-runtime
n
weird.. i seem to not have that class
d
and KSerializer?
well check the
JSON.stringify
arguments and cast to whatever it requests, it works because of the type erasure
so you can place the generic you need to match the one of the instance
n
KSerializer
works then i hope
👍 1
d
You can also do this:
Copy code
val clazz: KClass<Any> = obj::class as KClass<Any>
val serializer = clazz.serializer()
the problem is that
obj::class
returns
KClass<out T>
and you don’t need an out generic, but the specific one. Since the generic is erased, it is ok.
n
it WORKS.. i will do a PR to the kotlinxSerializer
👏 2
now i just need to find where that code lives
i am not sure if i should just allow to pass in a JSON object with default value
i am not even sure if this would work on non-jvm platforms.. it only depnds on common code as far as i can tell..
d
Looks fine to me. I would change the
as KSerializer<Any>
to the second trick:
val clazz: KClass<Any> = obj::class as KClass<Any>
since
KClass
is way more stable API than
KSerializer
. But that’s a minor observation
b
The hard part about reified types is type Erasure when creating the KClass via
::class
so you would only have a
List<*>
which isn't much better than Any IMO
s
The
::class.serializer()
will likely work for plain user types, but not for generic containers (like List<T>), because there are no information about T to get serializer for it. I suggest to use mentioned TypeInfo in conjuction with this method: https://github.com/Kotlin/kotlinx.serialization/blob/master/runtime/jvm/src/main/kotlin/kotlinx/serialization/Resolving.kt#L60
and bare lists seems to be a seperate issue for kotlinx-serialization, did not work for me, i had to wrap it in some text and deserialize as a class, just to take the list from it then
s
It is a known limitation that serializers for some classes (generic ones) can not be obtained from KClass. It is induced by reflectionless design and hard to change in the runtime itself.