Affects: 5.3.2


Having both Jackson and kotlinx.serialization in the classpath, kotlinx.serialization will try to deserialize Java interfaces implemented by Java classes resulting in the following exception:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Polymorphic serializer was not found for missing class discriminator ('null')
... nested exception is kotlinx.serialization.json.internal.JsonDecodingException: Polymorphic serializer was not found for missing class discriminator ('null')

The issue comes from the KotlinSerializationJsonHttpMessageConverter.candRead() method that returns true when the Type is a Java interface.

In case of Java concrete implementations, this method should return false and let Jackson handle the conversion.

Comment From: quaff

You could try https://github.com/FasterXML/jackson-modules-base/tree/master/mrbean , It will create an proxy implemented interface.

Comment From: sdeleuze

Good catch, I would expect SerializersKt.serializer(type) provided by kotlinx.serialization to throw an exception in that case, but indeed for some reasons it does not. I have raised that point to the Kotlin team, and will add a related check on Spring side and related tests as well.

Comment From: sdeleuze

I will wait for Kotlin team feedback since the check to use is not obvious because some Java interfaces should be supported (collections) while some others don't.

Comment From: tomfi

@scadgek will this solve the problem mentioned in #26321?

In my use-case I have both kotlin serialization and jackson in the classpath, but kotlin serialization was not configured for spring. in previous versions it did not affect anything but since this version spring try to use kotlin serialization in web requests which is not what i expected (or at least i expect to control it somehow)

Comment From: sdeleuze

@tomfi It should for non collection use cases, those who will be fixed via #26371. Please comment here if that's not the case.

Comment From: tomfi

@sdeleuze if i understand the fix correctly, it will throw exception in case it fails to find a serializer or it detect a polymorphic use case.

My problem is that first of all, the class that it try to serialzie/deserialize is not even my class, it belongs to spring security (DefaultOAuth2AccessToken).

And i think the root cause is because the change of order. I have both kotlin serialization and jackson in my classpath and now kotlin serialization is picked before jackson (unlike previous version) so it try to serialize/deserialize classes and interfaces with kotlin serialization which caused a regression.

In case is classes that are in my control i would fix it, but for spring security i can't really control it and in general can't really "tell" spring to prefer jackson over kotlin serialization or vice versa.

Hope it clarify a bit.

Edit: if i did not understand it correctly, and somehow it will "know" that the class/interface is not serializable by kotlin serialization and fallback to jackson then it solves my regression.

Comment From: sdeleuze

The exception will be catch on usage side, so in practice if that happens kotlin serialization will be skipped and jackson will be used. The order change has been done on purpose but to work in a reasonable way kotlin serialization should not catch serialization expected to be done by Jackson, hence this issue and #26371 for collections. So yes it should solve your regression if that's not a use case with collections. 5.3.3 has been released so feel free to test and send your feedback.

Comment From: tomfi

@sdeleuze sure, thanks for the clarifications 👍