You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
I’m using SerializersModule.serializer() to look up a serializer for my class when my service starts up. If a serializer is not available I expect this function to throw an exception. That way if there’s a configuration problem I find out early. Otherwise I only crash when I attempt to use the serializer.
Unfortunately kotlinx.serialization returns successfully when looking up the serializer for an interface type, even if no polymorphic serializers are registered for that type.
This is inconsistent with the behavior of serializers for concrete classes. In this case kotlinx.serialization throws an exception when requesting a serializer for a class that is not serializable.
To Reproduce
This case looks up serializers for 4 cases: serializable class, serializable interface, non-serializable class, and non-serializable interface. We expect the serializable types to return normally, and the non-serializable types to throw an exception. Unfortunately the test method nonSerializableInterface() doesn't throw an exception.
import kotlin.test.assertFailsWith
import kotlinx.serialization.Serializable
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.serializer
import org.junit.Test
class LookupInterfaceSerializerTest {
@Test
fun serializableClass() {
// This class is serializable so this completes normally.
serializersModule.serializer<SerializableClass>()
}
@Test
fun serializableInterface() {
// This interface is serializable so this completes normally.
serializersModule.serializer<SerializableInterface>()
}
@Test
fun nonSerializableClass() {
// This class is not serializable so requesting a serializer fails.
assertFailsWith<IllegalArgumentException> {
serializersModule.serializer<NonSerializableClass>()
}
}
@Test
fun nonSerializableInterface() {
// This interface is not serializable so requesting a serializer should fail. Unfortunately
// kotlinx.serialization succeeds here, but will crash later when the serializer is used.
assertFailsWith<IllegalArgumentException> {
serializersModule.serializer<NonSerializableInterface>()
}
}
}
private val serializersModule = SerializersModule {
polymorphic(
SerializableInterface::class,
RealSerializableInterface::class,
RealSerializableInterface.serializer()
)
}
@Serializable
class SerializableClass(val message: String)
interface SerializableInterface {
val message: String
}
@Serializable
class RealSerializableInterface(
override val message: String
) : SerializableInterface
class NonSerializableClass(val message: String)
interface NonSerializableInterface {
val message: String
}
Expected behavior
Exception thrown.
Environment
Kotlin version: 1.5.31
Library version: 1.3.1
Kotlin platforms: JVM
Gradle version: 7.0.2
The text was updated successfully, but these errors were encountered:
That's an interesting design issue. Normally, I would say that val serial = serializer<SomeInterface> should always return a polymorphic serializer because we can use it with any format and any module. However, top-level serializer<T>() is defined as EmptyModule.serializer<T>() and here you raise the issue about extension function and that's a tricky part, because actual lookup is performed in the format, not on the receiver module. As a consequence the following code works too:
val moduleThatContainsSubclasses =SerializersModule { ... }
val json =Json { module = moduleThatContainsSubclasses}
json.encodeToString(moduleThatDoesNotContainAnythingRelated.serializer<SomeInterface>, ...)
because actual lookup of subclasses is performed inside the module that passed to Json instance.
I do not think we are able to do something with it at this point — prohibiting resolving serializer<SomeInterface>() to polymorphic serializer is not correct, because such serializer can be used in any format which provides sufficient SerializersModule. SomeInterface is also treated as implicitly @Serializable by compiler, so there should be a feature parity. We did some tweaks (namely, context serializers now have priority over polymorphic for interfaces: #2060) to ease this problem, but it for now it is left as-is.
Describe the bug
I’m using
SerializersModule.serializer()
to look up a serializer for my class when my service starts up. If a serializer is not available I expect this function to throw an exception. That way if there’s a configuration problem I find out early. Otherwise I only crash when I attempt to use the serializer.Unfortunately kotlinx.serialization returns successfully when looking up the serializer for an interface type, even if no polymorphic serializers are registered for that type.
This is inconsistent with the behavior of serializers for concrete classes. In this case kotlinx.serialization throws an exception when requesting a serializer for a class that is not serializable.
To Reproduce
This case looks up serializers for 4 cases: serializable class, serializable interface, non-serializable class, and non-serializable interface. We expect the serializable types to return normally, and the non-serializable types to throw an exception. Unfortunately the test method
nonSerializableInterface()
doesn't throw an exception.Expected behavior
Exception thrown.
Environment
1.5.31
1.3.1
JVM
7.0.2
The text was updated successfully, but these errors were encountered: