Trqhxrd
Trqhxrd

Reputation: 53

kotlinx-serialization not generating serializer in companion of classes annotated with @Serializable

I'm currently trying to create a parent class that can be serialized but has no own attributes. (They will be added in the inheriting classes)

For some reason there is no serializer()-method being generated.

I checked the following things:

Thank you for reading my question.

This is the exception:

java.lang.NullPointerException: Cannot invoke "me.trqhxrd.grapesrpg.impl.world.predefined.Void$Companion.serializer()" because "me.trqhxrd.grapesrpg.impl.world.predefined.Void.Companion" is null
    at me.trqhxrd.grapesrpg.impl.world.BlockData.<clinit>(BlockData.kt:24) ~[GrapesRPG-1.0-SNAPSHOT-all.jar:?]
    ... 37 more

These code-snippets might be relevant:

build.gradle

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.6.21'
    id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
    id 'java'
}


group = 'me.trqhxrd'
version = '1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven {
        url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
    }
    maven {
        url 'https://repo.codemc.org/repository/maven-public/'
    }
    maven {
        url 'https://maven.wolfyscript.com/repository/public/'
    }
    maven {
        url 'https://mvn.trqhxrd.de/releases'
    }
}

dependencies {
    testImplementation 'org.jetbrains.kotlin:kotlin-test'
    testImplementation 'com.github.seeseemelk:MockBukkit-v1.18:1.24.1'

    compileOnly 'org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT'

    compileOnly 'org.eclipse.aether:aether-api:1.1.0'
    compileOnly 'org.eclipse.aether:aether-spi:1.1.0'
    compileOnly 'org.eclipse.aether:aether-connector-basic:1.1.0'
    compileOnly 'org.eclipse.aether:aether-transport-file:1.1.0'
    compileOnly 'org.eclipse.aether:aether-transport-http:1.1.0'
    compileOnly 'org.apache.maven:maven-aether-provider:3.3.9'
    compileOnly 'org.apache.maven.resolver:maven-resolver-connector-basic:1.8.0'

    compileOnly 'org.jetbrains.exposed:exposed-core:0.38.2'
    compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.38.2'
    compileOnly 'org.jetbrains.exposed:exposed-dao:0.38.2'
    compileOnly 'org.xerial:sqlite-jdbc:3.36.0.3'
    compileOnly 'com.zaxxer:HikariCP:5.0.1'
    compileOnly 'org.slf4j:slf4j-nop:2.0.0-alpha7'

    compileOnly 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21'
    compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.3.2'
    compileOnly 'org.jetbrains.kotlin:kotlin-reflect:1.6.21'

    compileOnly 'com.google.guava:guava:31.1-jre'

    shadow 'org.bstats:bstats-bukkit:3.0.0'
    shadow 'me.trqhxrd:menus:1.2.1'
    shadow 'com.wolfyscript.wolfyutils.spigot:wolfyutils-spigot:4.16.1.0'
    shadow 'de.tr7zw:item-nbt-api:2.9.2'
    shadow 'de.tr7zw:nbt-injector:2.9.2'
}

test {
    useJUnitPlatform()
}

compileKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

compileTestKotlin {
    kotlinOptions.jvmTarget = '1.8'
}

tasks.register('installPlugin', Copy) {
    dependsOn 'shadowJar'
    from layout.buildDirectory.dir("$buildDir/libs/GrapesRPG-1.0-SNAPSHOT-all.jar")
    into layout.buildDirectory.dir("$projectDir/Server/plugins")
}

configurations {
    shadow
    compile.extendsFrom provided
    provided.extendsFrom shadow
}

shadowJar {
    relocate 'org.bstats', 'me.trqhxrd.shade.bstats'

    configurations = [project.configurations.shadow]
    from(project.sourceSets.main.output)
}

The parent class


package me.trqhxrd.grapesrpg.impl.world

import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonObject
import me.trqhxrd.grapesrpg.impl.world.predefined.Void
import me.trqhxrd.grapesrpg.util.ModuleKey
import me.trqhxrd.grapesrpg.api.world.BlockData as BlockDataAPI

@Serializable
abstract class BlockData(override val id: ModuleKey) : BlockDataAPI {

    companion object {
        val registry = mutableMapOf<ModuleKey, Pair<Class<out BlockData>, KSerializer<out BlockData>>>()

        val KEY_VOID = ModuleKey("grapes", "void")

        init {
            registry[KEY_VOID] = Void::class.java to Void.serializer()
        }
    }

    override fun save() = Json.encodeToString(this)

    @Suppress("UNCHECKED_CAST")
    override fun load(serialized: String) {
        val key = Json.decodeFromJsonElement<ModuleKey>(
            Json.decodeFromString<JsonObject>(serialized)["id"]!!.jsonObject
        )

        val serializer = registry[key]!!.second

        val d = serializer.deserialize(Json.decodeFromString(serialized))
        if (this::class.java.isAssignableFrom(d::class.java)) this.apply(d)
    }

    override fun apply(data: BlockDataAPI) {
        if (!this::class.java.isAssignableFrom(data::class.java))
            throw IllegalArgumentException(
                "Can't load data from a class isn't assignable from the loading class. " +
                        "(Required: ${this::class.qualifiedName}, Received: ${data::class.qualifiedName})"
            )
    }
}

The child class


package me.trqhxrd.grapesrpg.impl.world.predefined

import kotlinx.serialization.Serializable
import me.trqhxrd.grapesrpg.impl.world.BlockData
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.event.player.PlayerInteractEvent

@Serializable
class Void : BlockData(KEY_VOID) {

    override fun onClick(event: PlayerInteractEvent) {}
    override fun onBreak(event: BlockBreakEvent) {}
    override fun onPlace(event: BlockPlaceEvent) {}
}

EDIT 1: I try to create a new object of the Void-class via the empty constructor.

EDIT 2: All the dependencies are compileOnly because this is a Minecraft-Plugin and most of the dependencies will be downloaded automatically by the Minecraft-Server. That way my Uber-Jar is smaller...

Upvotes: 0

Views: 1339

Answers (1)

Trqhxrd
Trqhxrd

Reputation: 53

Well I just gave up and used Gson. If anyone finds an answer that doesn't just avoid the problem by removing the library feel free to post it here and I'll mark it as correct. Thank you for reading...

Upvotes: 2

Related Questions