Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 348 Vote(s) - 3.54 Average
  • 1
  • 2
  • 3
  • 4
  • 5
kotlinx-serialization: Polymorphic serializer was not found for missing class discriminator ('null')

#1
I am trying to serialize a json, but its throwing JsonDecodingException. Check the code:

**SerializationTestCase.kt:**

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import org.junit.Test

class SerializationTestCase {

private val json = Json {
ignoreUnknownKeys = true
isLenient = true
prettyPrint = true
allowStructuredMapKeys = true
encodeDefaults = true
classDiscriminator = "#class"
serializersModule = SerializersModule {
polymorphic(Module::class) {
subclass(TeamModule::class, TeamModule.serializer())
}
}
}

@Test
fun test() {
val inputJson = """
[
{
"type": "team",
"data": {
"readOnly": true
}
}
]
""".trimIndent()

val moduleList: List<Module> = json.decodeFromString(inputJson)
println(moduleList)
}
}


@Serializable
sealed class Module(val type: String)

@Serializable
@SerialName("TeamModule")
data class TeamModule(val data: TeamData) : Module("team")

@Serializable
data class TeamData(
val readOnly: Boolean = false
)


**Error Log:**

kotlinx.serialization.json.internal.JsonDecodingException: Polymorphic serializer was not found for missing class discriminator ('null')
JSON input: {"type":"team","data":{"readOnly":true}}

at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.internal.PolymorphicKt.throwSerializerNotFound(Polymorphic.kt:80)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:70)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:32)
at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
at kotlinx.serialization.encoding.CompositeDecoder$DefaultImpls.decodeSerializableElement$default(Decoding.kt:536)
at kotlinx.serialization.internal.ListLikeSerializer.readElement(CollectionSerializers.kt:80)
at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:63)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:32)
at kotlinx.serialization.json.Json.decodeFromString(Json.kt:85)
at com.arinspect.domain.SerializationTestCase.test(SerializationTestCase.kt:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)


I went through the [documentation][1] and I am doing the same as asked, but still its not working as expected. Any help would be appreciated!

**PS:** Dependency I am using:

api "org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0"

and kotlin version is 1.4.31

Looks like this is an issue, I have reported this here:

[To see links please register here]



[1]:

[To see links please register here]

Reply

#2
We can use [JsonContentPolymorphicSerializer][1].

According to documentation:

> Base class for custom serializers that allows selecting polymorphic
> serializer without a dedicated class discriminator, on a content
> basis.

this is how I achieved:

class SerializationTestCase {

private val json = Json {
ignoreUnknownKeys = true
isLenient = true
prettyPrint = true
encodeDefaults = true
classDiscriminator = "#class"
}

@Test
fun test() {
val inputJson = """
[
{"type": "team","data": {"readOnly": true}},
{"type": "org","data": {"readOnly": true}}
]
""".trimIndent()

val moduleList: List<Module> =
json.decodeFromJsonElement(json.parseToJsonElement(inputJson))
println(moduleList)
}
}


@Serializable(with = ModuleSerializer::class)
sealed class Module {
abstract val type: String
}

@Serializable
data class TeamModule(val data: TeamData, override val type: String = "team") : Module()

@Serializable
data class OrgModule(val data: TeamData, override val type: String = "org") : Module()

@Serializable
data class TeamData(
val readOnly: Boolean = false
)

object ModuleSerializer : JsonContentPolymorphicSerializer<Module>(Module::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out Module> {
return when (element.jsonObject["type"]?.jsonPrimitive?.content) {
"team" -> TeamModule.serializer()
"org" -> OrgModule.serializer()
else -> throw Exception("Unknown Module: key 'type' not found or does not matches any module type")
}
}
}


[1]:

[To see links please register here]

Reply

#3
For those who seek to implement this without using `JsonContentPolymorphicSerializer`, you can utilize the `@SerialName` annotation on each class specifying correct ` discriminator` value and let the `kotlinx.serialization` do the processing.
<!-- language: kotlin -->

class SerializationTestCase {

private val json = Json {
ignoreUnknownKeys = true
isLenient = true
prettyPrint = true
allowStructuredMapKeys = true
encodeDefaults = true
classDiscriminator = "type" // default is "type", so you can just omit it
}

@Test
fun test() {
val inputJson = """
[
{
"type": "team",
"data": {
"readOnly": true
}
}
]
""".trimIndent()

val moduleList: List<Module> = json.decodeFromString(inputJson)
println(moduleList)
}
}


@Serializable
sealed class Module {
abstract val type: String
}

@Serializable
@SerialName("team") // <-- this is the class discriminator. It should match the value of the `type` property in the JSON.
data class TeamModule(override val type: String, val data: TeamData) : Module()

@Serializable
@SerialName("org") // <-- this is the class discriminator. It should match the value of the `type` property in the JSON.
data class OrgModule(override val type: String, val data: TeamData) : Module()

@Serializable
data class TeamData(
val readOnly: Boolean = false
)

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through