Java serialization is a dogs breakfast. Sometimes we need to protect code or data structures so that they are restricted to types that are serialization-safe. We could require that the parameter is Serializable, and while every Serializable is serializaton-safe, there are things that can be serialized that don’t implement Serializable. Can we do better?

Can we leverage Types-as-Proofs?
Following the glorious tradition of this blog, let’s treat this as a types-as-proofs problem. The proof we want is that the type can be serialized. So, naively, let’s directly represent this at a type.
trait CanBeSerialized[S]
This lets us protect methods with evidence that something can be serialized like this:
def sendOverRMI[S : CanBeSerialized](something: S) = ...
So, now we have protected sendOverRMI() so that it only accepts things that have evidence that they can be serialized. Now we just need some implicit witnesses. A good start is to allow all serializable types and all primitive types.
implicit def serializableIsSafe[S <: Serializable](s: S) =
new SerializationSafe[S] {}
implicit def valuesAreSafe[A <: AnyVal] =
new SerializationSafe[A] {}
There are probably other things that are serialization-safe. If you think of them, add an implicit. As you can see, this approach gives us an extensible way to protect code so that it only accepts serializaton-safe data. It’s decoupled from the Java Serialization interface just enough that we can accept the types we actually want. In retrospect, Java should have handled all serialization differently, either using a type-class approach or by explicitly exposing the meta-object responsible for serialization. However, given where we are now, the SerializationSafe type-class at least gives us a fig-leaf of safety in a mad world.
Putting it all together
You can find a sketch of this approach as a gist:
This code is untested and unused in any of my projects. Please pillage freely.