在运行时向序列化对象添加额外字段

Add extra field to an serialized Object at runtime

我想向对象添加一个额外的字段(例如 UUID),即将使用 javassist 或反射在运行时序列化或已经序列化。

可能吗?

简答

不能随心所欲,但也许还有其他方法

长答案

那么让我们从一些定义开始:

Javassist:是一个 class 库,用于在 Java 中编辑字节码。它使 Java 程序能够在运行时定义新的 class 并 modify a given class file when the JVM loads it.

反射: 是 Java 编程语言的一个特性。它允许正在执行的 Java 程序对自身 examine or introspect 和程序的 manipulate internal properties。例如,Java class 可以获取其所有成员的名称并显示它们。

因此,正如我用 Javassist 突出显示的那样,您可以轻松地将字段添加到 class 但 only at load time (这意味着当 JVM 将 classes 加载到其内存)。

使用 reflection 可以查找 class 的属性,甚至可以修改它们,但是有 no way off adding new properties.

我的提议

我现在不知道这对你的用例是否可行,但解决方案可能同时使用它们:

  1. 使用 Javassist 将提交的 UUID 添加到加载时可能需要它的 classes
  2. 在序列化对象之前,可以使用Reflection实际设置这个UUID字段为想要的值,然后再序列化

实际上,不需要反射就可以,不需要对要将自定义 属性 添加到其对象的 Class 有任何 window - 它可以首先完成像这样将您的对象转换为属性映射,

这是我为此编写的方法,

     /**
     * To convert the current Object to a AttributeMap. This allows for using this map
     * to add to it in a subclass additional attributes for Serialization. It would be
     * required in a scenario when you want to alter the simple Jackson Serialization
     * methodology(where you just annotate the fields to be included in Serialization
     * and that's it.). A non-simple scenario would involve adding custom fields decided
     * at runtime 
     * @return The AttributeMap of this object.
     */
    protected Map<String, Object> toAttributeMap(Object object){
        return objectMapper.convertValue(object, new TypeReference<Map<String, Object>>() {
        });
    }

现在,您可以将对象添加到此属性映射,然后将您的字段放入 () 并将其转换为可能 JSON 字符串。


答案注释:

  • 它使用 Jackson 的对象映射器 API。
  • 它不使用 JavaAssist。