kordlib/kord

Serializers should be public

Closed this issue · 16 comments

I've run into a problem while using Kord's Optional type - I can't use it in my own serialized structures because the serializer is marked internal!

It's important for all generic serializers to be public; otherwise it's impossible to wrap them when working with complex nested data structures. For example, something like this:

class MyClass <T: Any>{
	val optional: Optional<T> = ...
}

I cannot write a serializer for this type unless the Optional serializer is made public.

Please note that this is currently a blocker for KordEx.

you should be able to use Optional.serializer(tSerializer) to get an instance of OptionalSerializer

Nope.

image

what's the compiler error? it seems to work for me inside of kordex

Undefined reference - my IDE isn't seeing it either.

the function exists in the jar:

public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;

The commit you've linked seems to be in the K2 version, was that added in that version?

The commit you've linked seems to be in the K2 version, was that added in that version?

no, if you look at the blame, it's been there for 3 years

is Optional actually referring to the companion object in that screenshot? the fact that intellij shows it in an italic font makes me think it might not.

Think it might be an editor bug? I do have Kord's one imported...

Yep, editor bug. Fantastic. /s

Why does this function exist, though? The kotlinx.serialization docs refer to serializer classes for this use-case, not serializer functions.

Why does this function exist, though? The kotlinx.serialization docs refer to serializer classes for this use-case, not serializer functions.

kxser generates it for all classes annotated with @Serializable, no matter if it has a custom or generated serializer, see https://kotlinlang.org/api/kotlinx.serialization/kotlinx-serialization-core/kotlinx.serialization/-serializable/

Hmm, I figured that this needed a reified type, but I guess not.

Still, internal access seems unexpected given documented conventions - is there a reason to keep the serializer internal?

this way, you don't have to know whether some serializable class has a generated or hand-written serializer, it's just an implementation detail. this allows us to change the serializer without affecting the api surface.

Still, internal access seems unexpected given documented conventions

also where did you take this from?

The kx.ser docs

Seems expected that you'd have access to the actual serializer, esp. given the docs state that you must use them directly for collections, which are still essentially container classes for generic types.

Seems expected that you'd have access to the actual serializer, esp. given the docs state that you must use them directly for collections, which are still essentially container classes for generic types.

i don't see the benefit of exposing the classes, i think you can do everything you need to do with the generated serializer functions. after all a serializable generic container type with a generated serializer would have to be used this way too:

@Serializable
public data class MyGenericContainer<A, B>(val a: A, val b: B)

// the only way to use the serializer would be:
val serializer: KSerializer<MyGenericContainer<String, Int>> =
    MyGenericContainer.serializer(String.serializer(), Int.serializer())

The kx.ser docs

Seems expected that you'd have access to the actual serializer, esp. given the docs state that you must use them directly for collections, which are still essentially container classes for generic types.

Those are actually functions, there is no ListSerializer, and the actual implementation of most built in serializers is internal or marked with an internal opt in

https://github.com/Kotlin/kotlinx.serialization/tree/master/core/commonMain/src/kotlinx/serialization/builtins/BuiltinSerializers.kt#L208