protostuff icon indicating copy to clipboard operation
protostuff copied to clipboard

GraphIOUtil deserialize subclass of Map can not return custom variable

Open muyuqiu001 opened this issue 8 years ago • 6 comments

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.

muyuqiu001 avatar Oct 28 '16 08:10 muyuqiu001

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"

muyuqiu001 avatar Oct 28 '16 08:10 muyuqiu001

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);

dyu avatar Oct 28 '16 15:10 dyu

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

muyuqiu001 avatar Oct 29 '16 01:10 muyuqiu001

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.

dyu avatar Oct 29 '16 06:10 dyu

yes, after adding RuntimeSchema.map(TestMainData.class, TestMainData.class);,the sysout still is name=null, id=0 ,key=aaaa, value=bbb

muyuqiu001 avatar Oct 29 '16 07:10 muyuqiu001

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.

dyu avatar Oct 29 '16 10:10 dyu