question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SerializersModule doesn't prefer either contextual or subclass over plugin-generated serializers

See original GitHub issue

Describe the bug I have many serializers, which are build at runtime and customize the plugin-generated serializers. SerializersModule does not select them. It instead always uses the plugin-generated serializers.

To Reproduce

package com.issue

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import kotlin.test.Test
import kotlin.test.assertEquals

class IssueTest {

    @Serializable
    abstract class Project {
        abstract val name: String
    }

    @Serializable
    @SerialName("owned")
    class OwnedProject(override val name: String, val owner: String) : Project()

    class CustomOwnedProjectSerializer(private val customField: String) :
        JsonTransformingSerializer<OwnedProject>(OwnedProject.serializer()) {
        override fun transformSerialize(element: JsonElement): JsonElement {
            require(element is JsonObject)
            return JsonObject(
                mapOf(
                    "customType" to JsonPrimitive("project.owned"),
                    "customField" to JsonPrimitive(customField),
                    *element.entries.map { Pair(it.key, it.value) }.toTypedArray()
                )
            )
        }
    }

    val module = SerializersModule {
        contextual(CustomOwnedProjectSerializer("unicorn"))
        polymorphic(Project::class) {
            subclass(CustomOwnedProjectSerializer("unicorn"))
        }
    }

    val format = Json { serializersModule = module }


    @Test
    fun test() {
        val data = OwnedProject("kotlinx.coroutines", "kotlin")
        val expectedJson =
            """{"customType":"project.owned","customField":"unicorn","name":"kotlinx.coroutines","owner":"kotlin"}"""
        assertEquals(expectedJson, format.encodeToString(CustomOwnedProjectSerializer("unicorn"), data)) // works
        assertEquals(expectedJson, format.encodeToString<Project>(data)) // does not work
        assertEquals(expectedJson, format.encodeToString(data)) // does not work
    }
}

Expected behavior I expect, that SerializersModule prefers registered serializers over plugin-generated serializers.

Environment

  • Kotlin version: 1.4.21
  • Library version: 1.0.1
  • Kotlin platforms: multiplatform (JVM/JS/Native)]
  • Gradle version: 6.8

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
shanshincommented, Feb 9, 2021

This is a bug in polymorphism using JsonTransformingSerializer child serializer: #1329. As a temporary workaround, you may try to create a surrogate class (see https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#composite-serializer-via-surrogate).

0reactions
benkulycommented, Feb 9, 2021

@sandwwraith any idea?

Read more comments on GitHub >

github_iconTop Results From Across the Web

json - kotlin: nested polymorphic serialization with generics
How to register the Pair as polymorphic subclass for that? val module = SerializersModule { polymorphic(Any::class) { subclass(Int::class ...
Read more >
ContextualSerializer - Kotlin
ContextualSerializer ... This class provides support for retrieving a serializer in runtime, instead of using the one precompiled by the serialization plugin.
Read more >
Third-party sealed classes serialization with `kotlinx ... - Medium
I like reading articles and looking directly in the code. If you are like me, please go directly to the repo.
Read more >
Serializing Django objects
At the highest level, you can serialize data like this: ... Call the serializer on the object (or objects) that you want to...
Read more >
No contextual serializers when KotlinxSerializationConverter ...
If I add a custom serializer to the Json , it doesn't work with Ktor, meanwhile, ... serializersModule = SerializersModule { contextual(Either::class) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found