使用不同的包名称对不同应用程序中的java对象进行de/serialize

mat*_*ger 4 java serializable

我想在不同的应用程序之间共享java对象.

只要我在不同的项目中使用相同的包名称,它就可以正常工作.但是,如果我更改包名称,它就不再起作用了.

我试图通过扩展ObjectInputStream类并重写readClassDescriptor方法来解决这个问题.

但通过这样做,我收到以下错误:

java.io.StreamCorruptedException: invalid type code: 00
Run Code Online (Sandbox Code Playgroud)

......不知道如何解决这个问题.

这是我用于扩展ObjectInputStream类的代码:

public class MyObjectInputStream extends ObjectInputStream {

    public static Map<String, Class> classNameMapping = initclassNameMapping(); 

    private static Map<String, Class> initclassNameMapping(){
        Map<String, Class> res = new HashMap<String, Class>();
        //ipxTest is the name of the package where the objects got serialized
        res.put("ipxTest.IPX", interprojectxchangeTest.IPX.class); 
        res.put("ipxTest.A", interprojectxchangeTest.A.class);
        return Collections.unmodifiableMap(res);
    }

    public MyObjectInputStream(InputStream in) throws IOException {
        super(in);
        enableResolveObject(true);
    }


    protected MyObjectInputStream() throws IOException, SecurityException {
        super();
        enableResolveObject(true);
    }

    @Override
    protected java.io.ObjectStreamClass readClassDescriptor() 
            throws IOException, ClassNotFoundException {
        ObjectStreamClass desc = super.readClassDescriptor();
        if (classNameMapping.containsKey(desc.getName()))
            return ObjectStreamClass.lookup(classNameMapping.get(desc.getName()));
        return desc;
    }
}
Run Code Online (Sandbox Code Playgroud)

IPX和A类在不同的项目中看起来相同,并且每个类都具有相同的serialID.

Gre*_*eek 7

我的第一个建议是简化您的实现并停止对框架的攻击 - 在应用程序中使用相同的包名称.我建议从可序列化的类中创建一个库,并在实现之间共享它.

如果必须在具有不同软件包名称的应用程序之间进行序列化/反序列化,那么我的建议是放弃内置的Java序列化,它与类名和包名紧密相关,并使用类似Gson的序列化/反序列化.

Gson允许您指定TypeAdaper.您可以为要序列化/反序列化的每个类创建和注册TypeAdapter,并在序列化时将类名称(没有包名称)指定为"类型",如下例所示,但使用getSimpleName()而不是getCanonicalName( )

反序列化时,您必须将正确的包名称添加到"类型"

您必须为每个应用程序单独执行TypeAdapter.

public class GsonTypeAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {
    @Override
    public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject result = new JsonObject();
        result.add("type", new JsonPrimitive(src.getClass().getCanonicalName()));
        result.add("properties", context.serialize(src, src.getClass()));

        return result;
    }

    @Override
    public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        String type = jsonObject.get("type").getAsString();
        JsonElement element = jsonObject.get("properties");

        try {
            return context.deserialize(element, Class.forName(type));
        } catch (ClassNotFoundException cnfe) {
            throw new JsonParseException("Unknown element type: " + type, cnfe);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)