Search code examples
scalaserializationscala-2.10kryo

How do you deserialize immutable collection using Kryo?


How do you deserialize immutable collection using Kryo ? Do I need to register something in addition to what I've done ?

Here is my sample code

import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import com.romix.scala.serialization.kryo._

val kryo = new Kryo

// Serialization of Scala maps like Trees, etc
kryo.addDefaultSerializer(classOf[scala.collection.Map[_,_]], classOf[ScalaMapSerializer])
kryo.addDefaultSerializer(classOf[scala.collection.generic.MapFactory[scala.collection.Map]], classOf[ScalaMapSerializer])

// Serialization of Scala sets
kryo.addDefaultSerializer(classOf[scala.collection.Set[_]], classOf[ScalaSetSerializer])
kryo.addDefaultSerializer(classOf[scala.collection.generic.SetFactory[scala.collection.Set]], classOf[ScalaSetSerializer])

// Serialization of all Traversable Scala collections like Lists, Vectors, etc
kryo.addDefaultSerializer(classOf[scala.collection.Traversable[_]], classOf[ScalaCollectionSerializer])

val filename = "c:\\aaa.bin"
val ofile = new FileOutputStream(filename)
val output2 = new BufferedOutputStream(ofile)
val output = new Output(output2)
kryo.writeClassAndObject(output, List("Test1", "Test2"))
output.close()

val ifile = new FileInputStream(filename)
val input = new Input(new BufferedInputStream(ifile))
val deserialized = kryo.readClassAndObject(input)
input.close()

It throws exception

Exception in thread "main" com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): scala.collection.immutable.$colon$colon

Solution

  • Try this out as it worked for me:

    import com.esotericsoftware.kryo.Kryo
    import com.esotericsoftware.kryo.io.Input
    import com.esotericsoftware.kryo.io.Output
    import com.romix.scala.serialization.kryo._
    import org.objenesis.strategy.StdInstantiatorStrategy
    
    val kryo = new Kryo
    
    kryo.setRegistrationRequired(false)
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
    kryo.register(classOf[scala.collection.immutable.$colon$colon[_]],60)
    kryo.register(classOf[scala.collection.immutable.Nil$],61)
    kryo.addDefaultSerializer(classOf[scala.Enumeration#Value], classOf[EnumerationSerializer])
    
    val filename = "c:\\aaa.bin"
    val ofile = new FileOutputStream(filename)
    val output2 = new BufferedOutputStream(ofile)
    val output = new Output(output2)
    kryo.writeClassAndObject(output, List("Test1", "Test2"))
    output.close()
    
    val ifile = new FileInputStream(filename)
    val input = new Input(new BufferedInputStream(ifile))
    val deserialized = kryo.readClassAndObject(input)
    input.close() 
    

    As an FYI, I got this working by looking at the unit tests for the romix library and then doing what they were doing.