Java 处理不再存在的枚举值的反序列化

Java 处理不再存在的枚举值的反序列化,java,serialization,enums,Java,Serialization,Enums,我有一个enum JJJ,它有3个值:A、B和C。在我的程序的早期版本中,它有一个附加值:D。我希望能够读入由早期版本的程序创建的序列化对象,但当它在序列化对象中遇到值为“D”的JJJ类型变量时,会引发异常。最理想的情况是,我希望能够拦截反序列化过程,并告诉它在遇到d时只映射到C 根据(枚举常量的序列化),听起来似乎没有一种简单的方法可以做到这一点。。。我知道一种方法是在包含JJJ类型成员变量的类上重写readObject,但由于程序的大小和范围,这将是困难和痛苦的(几十个可序列化类都有JJJ类

我有一个enum JJJ,它有3个值:A、B和C。在我的程序的早期版本中,它有一个附加值:D。我希望能够读入由早期版本的程序创建的序列化对象,但当它在序列化对象中遇到值为“D”的JJJ类型变量时,会引发异常。最理想的情况是,我希望能够拦截反序列化过程,并告诉它在遇到d时只映射到C

根据(枚举常量的序列化),听起来似乎没有一种简单的方法可以做到这一点。。。我知道一种方法是在包含JJJ类型成员变量的类上重写readObject,但由于程序的大小和范围,这将是困难和痛苦的(几十个可序列化类都有JJJ类型的成员变量,重写readObject来处理JJJ字段意味着我还必须手动处理所有其他字段)

我还尝试通过滚动我自己的ObjectInputStream子类来解决这个问题,但不幸的是,我真正需要获取并重写的枚举反序列化位都是私有的或包私有的


有什么建议吗?

我还没有尝试过这个方法,但也许它可以奏效:

  • 创建一个新类“oldClass”,其字段与旧类完全相同

  • 扩展ObjectInputStream,以便在“oldClass”的实例中进行反序列化

  • 在您创建的“oldClass”中,实现“readResolve()”,以便返回新版本的类的实例,并根据需要更改缺少的字段


  • 仅供参考,对于其他试图处理此案件的可怜人,这是我最终实施的解决方案:

    我为枚举创建了一个特殊接口,如下所示:

    public interface SerialCompatEnum {
        public String convertOldValue(String oldValue);
    }
    
    然后,我编写了一个类,该类将原始序列化java对象字节流作为输入,对其进行处理,并将字节流的修改版本写入任意输出流当前代码库中实际存在的更新字符串。我们首先通过此处理器运行所有序列化对象,以防止因缺少枚举常量而导致的全部失败


    不幸的是,这不是一个非常干净或简单的解决方案。:/

    这就是为什么序列化不适合长期存储数据的一个例子:序列化的文件与源代码紧密耦合。使用标准的、有良好文档记录的、可扩展的格式来长期存储数据,而不是Java序列化。是否可以重新添加
    D
    和至少,为了迁移所需的时间,请将其标记为已弃用?或者这会破坏其他代码?@Lukas-我想将d排除在枚举之外;程序的其他部分出于各种目的迭代此枚举的值,并且需要进行调整以支持遗留的不需要的值。以更好的格式序列化?除了笑话,您不能使用ol吗d枚举,并在加载后将所有Ds转换为Cs?@Jesper-虽然Java序列化在用于此目的时确实存在一些缺点,但它也提供了许多好处,例如减轻程序员序列化数据的负担,并且没有太多的样板代码来执行例程对象序列化之类的操作未来我们将能够迁移到更灵活的框架…不幸的是,您无法在枚举上实现“readResolve()”(您可以,但它不会被调用~)任何特定的代码示例(请?:)最近正在努力从javax.ws.rs.core.Response获取这些字节流,并在读取实体之前对其进行处理,但我肯定错过了什么。。。最终实现了API的替代版本以避免所有痛苦:)我编写的处理实际字节流修改的类是一个大约1500行的混乱,基本上是Java序列化对象语法/格式的基于流的解析器的完整实现。它目前的形式并不可移植,但我可能会尝试在将来的某一天将其重新制作成一个合适的库。