Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.34k stars 618 forks source link

Provide public API for external polymorphic and/or sealed serializers #2460

Open qwwdfsad opened 11 months ago

qwwdfsad commented 11 months ago

Currently, the general-purpose (i.e. not JSON-specific) polymorphism is supported only by subclassing AbstractPolymorphicSerializer with internal constructor.

The rationale is basically the same as in #2459: the library has to implement an external sealed class serializer (example: https://github.com/Kotlin/kotlinx-datetime/blob/master/core/common/src/serializers/DateTimeUnitSerializers.kt#L190) but in the manner that this is a public type that can be used as @Serializable(with = ExternalSerializer).

Implementing regular serializer via delegation does not do the trick because all the format mplementations check for is AbstractPolymorphicSerializer

pdvrieze commented 11 months ago

@qwwdfsad Not all formats, in XML I don't check for that type (try to rely on descriptors only). Its implementation handles sealed and non-sealed separately, the default cases (no additional configuration) relying on the experimental SerializersModule.getPolymorphicDescriptors.

XML needs to do this as uses a two-phase approach where before serialization the system first builds up an extended type tree (without accessing serializer/serializer, only using the descriptors). This approach is there to have consistency between serialization and deserialization in a context where there is a policy that can influence how specific members are serialized.

The side-effect is that as long as the descriptor is "correct" (has a context) delegation of a polymorphic serializer is actually supported. It would be good if the SerialDescriptor wrapping function retained context though - that would allow renaming.

Looking at the problem, it should be perfectly possible to adjust the library so that the extension functions are no longer AbstractPolymorphicSerializer<T>.findPolymorphicSerializer but instead Serializer<T>.findPolymorphicSerializer (or even just the descriptor).

Having said that, this is one of the two points in the API that are clumsy at best:

sandwwraith commented 11 months ago

Related: #1715