Beginning serialization Q - java.io.Serializable to @Serializable

I’m trying to get a hello-world of serialization working after seeing it being ready in 1.4 (yay!)

I’ve got a class

class SimpleCache<K : Serializable, V : Serializable> {
  private val cache: MutableMap<K, V> =  ConcurrentHashMap()
  fun persist() {
    ObjectOutputStream(cacheFile.outputStream()).use {
      it.writeObject(cache)
    }
  }
}

But all of the Kotlin Serialization guide uses Annotations, not implementations of the java.io.Serializable interface. It even says “Serializable classes have to be explicitly marked.”

I’d like to change the above persist() example to store the map in a Cbor.encodeToByteArray(cache) then write the bytes to a file. Is there an easy way to move over? I think I assumed implementing the java.io.Serializable type params would do the trick, or that I could somehow indicate that the type params were @Serializable.

Thanks for any suggestions!

Kotlinx.serialization does not use any Java interface as it’s multiplatform, you will have implement a “bridge” between kotlinx.serialization process and Java Serializable interface

1 Like

Fair! … any thoughts on how?
(I imagine this is a common need - people who are looking to break free of JVM only and need to move over)

Java Serialization and kotlinx.serialization are quite different. Javas serialization is specific to JVM and is designed to store java objects, complete with type information and everything. It relies on support from the JVM itself.

kotlinx.serialization, however, is designed to be a multiplatform tool for mapping kotlin objects to and from generic formats, primarily JSON. In order to work on native platforms, which has very limited reflection support, it relies on serializers being generated at compile time for each class that needs to be serialized. This is where @Serializable comes into the picture. It is not used for anything interesting at runtime. It is used by the compiler plugin, which generates serializers for classes annotated with @Serializable. There are also ways to define serializers for third-party classes not annotated with @Serializable, which is described in the manual, but they still require you to define serializers for each class at compile time.

1 Like

Huh. Ok - so… (thinking)…

Is there any way to tell the compiler “Hey you! For any class in this package that implements java.io.Serializable, please consider it tagged @Serializable. Thanks!”

Otherwise, I’m not sure if it is possible to do in a clean generic way what I’m trying to do. I don’t know how to enforce type constraints that require the class types to be tagged “@Serializable” the same that I can require it to be implementing java.io.Serializable.

I naively tried the following, didn’t compile. (but tells you where my wishful thinking mind was at after reading the Annotations doc.

class SimpleCache<@Serializable K : Any, @Serializable V : Any>...

https://stackoverflow.com/questions/48980170/kotlin-annotation-as-generic-function-parameter talks about using reflections to check for an annotation, but I was hoping (fingers crossed) to not require it in the same way that Kotlinx.serialization doesn’t require serialization.

I see what you want, unfortunately I had the same issue and never found a workaround, I ended up sacrificing compiler safety and doing reflection based detection using serializerOrNull() on the KClass instance.

I think i’m going to open an issue on their github (if I don’t find one open already).

I’m not sure if they would accept it though because their philosophy is to hide (using the BINARY retention policy) any reference to the serialization annotation to keep the objects “clean” and I don’t know if adding an interface automatically fits in here.

1 Like

LMK and I’ll upvote it!

I think the simplest way I can describe it is “In a function that uses generics, is it possible to restrict to Kotlin @Serializable types being passed in?”

I opened the issue there