BenWoodworth / knbt

Kotlin NBT library for kotlinx.serialization
GNU Lesser General Public License v3.0
79 stars 3 forks source link

Serializing NbtTag results in a SerializationException #14

Closed Gaming32 closed 1 year ago

Gaming32 commented 2 years ago

If you attempt to serialize an NbtTag and have a subclass of that tag, a SerializationException occurs.

Exception in thread "main" kotlinx.serialization.SerializationException: Class 'NbtCompound' is not registered for polymorphic serialization in the scope of 'NbtTag'.
Mark the base class as 'sealed' or register the serializer explicitly.
    at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102)
    at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:113)
    at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:229)
    at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeNullableSerializableValue(Encoding.kt:299)
    at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableValue(AbstractEncoder.kt:18)
    at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableElement(AbstractEncoder.kt:90)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeNullableSerializableElement(StreamingJsonEncoder.kt:154)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:224)
    at kotlinx.serialization.internal.NullableSerializer.serialize(NullableSerializer.kt:23)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:224)
    at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80)
    at kotlinx.serialization.internal.CollectionLikeSerializer.serialize(CollectionSerializers.kt:69)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:224)
    at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80)
    at io.github.gaming32.mckt.PlayerData.write$Self(world.kt:494)
    at io.github.gaming32.mckt.PlayerData$$serializer.serialize(world.kt:494)
    at io.github.gaming32.mckt.PlayerData$$serializer.serialize(world.kt:494)
    at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:224)
    at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:28)
    at kotlinx.serialization.json.JvmStreamsKt.encodeToStream(JvmStreams.kt:25)
    ... 19 definitely unrelated frames
Gaming32 commented 2 years ago

Maybe this is correct that it should error here, but this exception is not a very useful error message for users of knbt.

BenWoodworth commented 2 years ago

Good callout!

I know the version of kotlinx.serialization that knbt v0.11 uses didn't properly support marking sealed interfaces @Serializable (which works seamlessly with sealed classes) and I had to special case NbtTag serialization. Might just be a matter of updating kotlinx.serialization to v1.4.0 so it has the fix, or maybe compiling against a newer version of Kotlin with a fixed serializer compiler plugin

Just added some tests locally to see if I could reproduce this, and I did get a failure with something I expected to work, though the error is different. That's something I'll have to fix

image

BenWoodworth commented 2 years ago

Could you share a reproducer to make sure I found the same issue? And maybe the kotlinx.serialization plugin version your project's using?

gradle :dependencies
Gaming32 commented 2 years ago

I'm on kotlinx.serialization 1.4.0. Your code is pretty much what I had, so it's definitely the same issue.