Deserialization problem for the classes which extend the implementation classes of Java collection
GoogleCodeExporter opened this issue · comments
Google Code Exporter commented
My test class extends ArrayList and has a _name attribute. By Kryo
deserializer, the _name attribute stays null, can't be read correctly.
public class TestClassForList extends ArrayList<String>
{
private static final long serialVersionUID = 8944285015775325886L;
String _name;
public String getName()
{
return _name;
}
public void setName( String name )
{
_name = name;
}
@Override
public boolean equals( Object o )
{
TestClassForList obj = (TestClassForList) o;
return super.equals( obj ) && _name.equals( obj.getName() );
}
}
Test Method:
@Test
public void validateList()
{
TestClassForList testClass = new TestClassForList();
testClass.add( "value" );
testClass.setName( "name" );
Kryo kryo = new Kryo();
ByteArrayOutputStream os = new ByteArrayOutputStream();
Output output = new Output( os );
kryo.writeClassAndObject( output, testClass );
output.flush();
ByteArrayInputStream is = new ByteArrayInputStream( os.toByteArray() );
Input input = new Input( is );
TestClassForList readObject = (TestClassForList) kryo.readClassAndObject( input );
assertEquals( testClass.getName(), readObject.getName() );
}
The test failed with output:
java.lang.AssertionError: expected:<name> but was:<null>
at org.junit.Assert.fail(Assert.java:91)
at org.junit.Assert.failNotEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:126)
at org.junit.Assert.assertEquals(Assert.java:145)
at blackboard.redis.serialization.KryoTest.validateList(KryoTest.java:61)
As to this problem, now we have to write a customised serializer which can set
Name in read(...) method.
Although this can resolve issue, this still makes our code not reliable because
we need to keep adding the customised serializer.
Can this be resolved by kryo?
Original issue reported on code.google.com by yangzhao...@gmail.com
on 18 Oct 2013 at 5:46
Google Code Exporter commented
I tested against kryo 2.22.
Original comment by yangzhao...@gmail.com
on 18 Oct 2013 at 5:56
- Added labels: ****
- Removed labels: ****
Google Code Exporter commented
You do not provide a custom serializer for your class. Therefore Kryo tries to
guess a matching serializer. It correctly detects that your class is derived
from ArrayList. Therefore it tries to use a corresponding default collection
serializer which is able to serialize ArrayLists. The problem is that this
serializer can serialize only vanilla collection classes, without any
additional fields.
Two solve your problem, I see two possibilities:
1) You create your own serializer for your class. It can be derived from a
CollectionSerializer. Your serializer first performs super.write (super.read)
and then writes/reads your additional field. Then you register your serializer
to be used for your class.
2) You rewrite your class in such a way that it uses composition instead of
inheritance. Done this way, it would contain two fields: one field containing
an ArrayList and one field containing a name. Due to this changed structure,
Kryo would use FieldSerializer for it and perform serialization properly.
I hope these suggestions help you to solve your problem.
Original comment by romixlev
on 18 Oct 2013 at 7:33
- Added labels: ****
- Removed labels: ****