protostuff
protostuff copied to clipboard
GraphIOUtil deserialize subclass of Map can not return custom variable
hello~ when i serialize a ClassA contains a value ClassB implement Map (there are some custom value in ClassB ) , but when i deserialize ClassA , ClassB custom value has gone.
here is my code:
package com.yoyo.test.protostuff;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.dyuproject.protostuff.GraphIOUtil;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
public class TestMain
{
public static void main(String[] args) throws IOException
{
TestMainData testdata = new TestMainData("test", 123);
ObjPackage obj = new ObjPackage();
obj.setObj(testdata);
testdata.put("aaaa", "bbb");
Schema<ObjPackage> schema = RuntimeSchema.getSchema(ObjPackage.class);
LinkedBuffer buffer = LinkedBuffer.allocate(256);
ByteArrayOutputStream oss = new ByteArrayOutputStream(1024);
GraphIOUtil.writeTo(oss, obj, schema, buffer);
ObjPackage objPack1 = new ObjPackage();
GraphIOUtil.mergeFrom(oss.toByteArray(), objPack1, schema);
System.out.println(objPack1);
}
}
class ObjPackage
{
public Object getObj()
{
return this.obj;
}
public ObjPackage setObj(Object obj)
{
this.obj = obj;
return this;
}
private Object obj;
public String toString()
{
return obj.toString();
}
}
class TestMainData implements Map<String, Object>
{
protected ConcurrentHashMap<String, Object> voProperties = new ConcurrentHashMap<String, Object>();
private String name;
private int id;
public TestMainData()
{
}
public TestMainData(String name, int id)
{
this.name = name;
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
@Override
public int size()
{
return voProperties.size();
}
@Override
public boolean isEmpty()
{
return voProperties.size() == 0;
}
@Override
public boolean containsKey(Object key)
{
return voProperties.containsKey(key);
}
@Override
public boolean containsValue(Object value)
{
return voProperties.containsValue(value);
}
@Override
public Object get(Object key)
{
return voProperties.get(key);
}
@Override
public Object put(String key, Object value)
{
return voProperties.put(key, value);
}
@Override
public Object remove(Object key)
{
return voProperties.remove(key);
}
@Override
public void putAll(Map<? extends String, ? extends Object> m)
{
voProperties.putAll(m);
}
@Override
public void clear()
{
voProperties.clear();
}
@Override
public Set<String> keySet()
{
return voProperties.keySet();
}
@Override
public Collection<Object> values()
{
return voProperties.values();
}
@Override
public Set<java.util.Map.Entry<String, Object>> entrySet()
{
return voProperties.entrySet();
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("name=").append(name).append(", id=").append(id);
for (String key : voProperties.keySet())
{
sb.append(" ,key=").append(key).append(", value=").append(voProperties.get(key));
}
return sb.toString();
}
}
i want get the result is "name=test, id=123 ,key=aaaa, value=bbb" but in fact is "name=null, id=0 ,key=aaaa, value=bbb"
Protostuff treats your pojo as a map hence it doesn't serialize its fields (just the entries). If your pojos implement Map/Collection/List, register them on startup/init like this:
RuntimeSchema.map(TestMainData.class, TestMainData.class);
I have tried,but it does not work.
public static void main(String[] args) throws IOException
{
TestMainData testdata = new TestMainData("test", 123);
ObjPackage obj = new ObjPackage();
obj.setObj(testdata);
testdata.put("aaaa", "bbb");
Schema<ObjPackage> schema = RuntimeSchema.getSchema(ObjPackage.class);
RuntimeSchema.map(TestMainData.class, TestMainData.class);
LinkedBuffer buffer = LinkedBuffer.allocate(256);
ByteArrayOutputStream oss = new ByteArrayOutputStream(1024);
GraphIOUtil.writeTo(oss, obj, schema, buffer);
ObjPackage objPack1 = new ObjPackage();
GraphIOUtil.mergeFrom(oss.toByteArray(), objPack1, schema);
System.out.println(objPack1);
}
result is still name=null, id=0 ,key=aaaa, value=bbb
and we have so many classes extend TestMainData, if up is work, should i call RuntimeSchema.map one time for super class(TestMainData) or call many times for every class that extend TestMainData?
Thanks
Do the latter. Every class that extends it (or directly implements Map/Collection/List) need to be registered.
Let me know if you still have problems after doing that.
yes, after adding RuntimeSchema.map(TestMainData.class, TestMainData.class);
,the sysout still is
name=null, id=0 ,key=aaaa, value=bbb
Ok. There were internal changes needed to make this work.
Try using 1.0.12-SNAPSHOT and instead of calling RuntimeSchema.map
, do:
RuntimeSchema.register(TestMain.class); // lazy registration
1.0.12 should be available in a few hours.