Hello, I've just updated serialization library fro...
# serialization
a
Hello, I've just updated serialization library from 0.10.0 to 0.11.0 and now getting error: Unresolved reference: registerSerializer and Classifier 'PolymorphicSerializer' does not have a companion object, and thus must be initialized here
Copy code
// * We need to register serializers for this RequestForChangeEvent to allow proper serialization for this type
    companion object {
        init {
            registerSerializer(RequestForChangeEvent::class.java.name, RequestForChangeEvent.serializer(PolymorphicSerializer))
            registerSerializer(ChangeRejectedEvent::class.java.name, ChangeRejectedEvent.serializer(PolymorphicSerializer))
            registerSerializer(ChangeAcceptedEvent::class.java.name, ChangeAcceptedEvent.serializer(PolymorphicSerializer))
        }
    }
how can I fix this?
s
Polymorphic serialization was rewritten so it can work on JS and Native, too. Take a look at the updated KDoc: https://github.com/Kotlin/kotlinx.serialization/blob/master/runtime/common/src/main/kotlin/kotlinx/serialization/Polymorphic.kt#L30
p
Can't you change it back that one doesn't need to manually add all the modules manually whenever he's using json?
s
top-level
registerSerializer
was registering classes in a global map. Global variables (especially mutable) are a very error-prone practice and hard to use in Kotlin/Native memory model
Generally, you need to write and register modules only once; then you pass
Json
instance with registered modules around your program where you want
p
I don't want to do that for simplicity reasons. When I have a sealed class, I want to have exactly one serializer. Isn't there a way of just annotating a sealed class and saying
@UseSerializer(xx))
and it always uses that polymorphic serializer?
a
I have
Copy code
@Serializable
data class RequestForChangeEvent<out T : EditableEvent>(
   val data: T
)
And I want to get a this class serializer with type T serializers of Polymorphic
Copy code
val serializer = RequestForChangeEvent.serializer(PolymorphicSerializer)
how this would look in 0.11.0?
Or I need to call PolymorphicSerializer(Any::class) constructor?
maybe I can just annotate 'data' property with '@Polymorphic' and it will work by default?
?
and question do all classes which is annotated with @Serializable will be automatically included and registered to polymorphic resolvable class list, or it's needed explicitly to list all classes which can be given to polymorphic property
p
@sandwwraith What do you tink about an api like this: https://gist.github.com/PaulWoitaschek/4f8b2ce13d1a0d49720c7dfaaf6183d1
With reflection and getting the sealed classes or with the compiler this could easily be implemented to handle sealed classes without the need to register the stuff manually. I mean in the end I just want to say: This is the class and let the compiler figure out the rest automagically, I don't want to maintain my own registry and pass it everywhere around
s
@Antanas A. you can either annotate
data
with
@Polymorphic
or create
RequestForChangeEvent.serializer(PolymorphicSerializer(EditableEvent::class))
Then you register all serializable sublcasses of
EditableEvent
in some module, and construct your format instance with this module
a
Thanks, but how exactly to use @Polymorphic?
Copy code
@Serializable
data class ChangeRejectedEvent<out T : EditableEvent>(
    val guid: GUID,
    val ref: GUID, // reference to RequestForChangeEvent
    val eventAt: Timestamp,
    val rejectedBy: RejectedBy,
    @Polymorphic val data: T
)
will this by default use PolymorphicSerializer(EditableEvent::class)
or I need use:
Copy code
@Serializable
data class ChangeRejectedEvent(
    val guid: GUID,
    val ref: GUID, // reference to RequestForChangeEvent
    val eventAt: Timestamp,
    val rejectedBy: RejectedBy,
    @Polymorphic val data: EditableEvent // <- here
)
s
hm, since this class still have
T
type param, you still need to construct it from
PolymorphicSerializer(EditableEvent::class)
if you remove
T
,
@Polymorphic
will do what you want
a
su that @Polymorphic annootation for this generic type
is with no use?
s
i'm afraid yes for now. Maybe this will be improved
a
maybe it would be possible to infer from type bounds which polymorphic serializer is used
understood, but we won't use any T parameters when what type of polymorphic serializer will be used on annotated parameter?
Any::class?
or it will be return type of parameter
@Polymorphic val data: ABCD --> will use PolymorphicSerializer(ABCD::class) or PolymorphicSerializer(Any::class) ?
s
@Paul Woitaschek what you're talking about is 'register all subclasses of sealed class at compile time', which is applicable only for, well, sealed classes. This is exactly what I meant when I said 'We have plans to improve it in future'. Polymorphic on sealed classes will work more or less like this, it is just not implemented yet, so for now you have to register modules as in usual case with
abstract
classes
@Antanas A.
@Polymorphic val data: ABCD
produces
PolymorphicSerializer(ABCD::class)
a
!
this should work for us, thanks