如何用我自己的readObject调用替换Java的默认反序列化?

时间:2014-10-08 15:12:47

标签: java deserialization

有人认为使用Java的默认序列化方法将对象存储在blob列的数据库中是个好主意。 这些对象的结构由另一个组控制,他们将字段类型从BigDecimal更改为Long, 但我们数据库中的数据保持不变。 现在我们无法读取对象,因为它会导致ClassCastExceptions。

我尝试通过编写自己的readObject方法来覆盖它, 但是抛出StreamCorruptedException,因为默认的writeObject方法写了什么。

如何使我的readObject调用表现得像Java的默认调用? 我可以跳过一定数量的字节来获取数据吗?

3 个答案:

答案 0 :(得分:2)

Externalizable允许您完全控制序列化/反序列化。但这意味着你负责编写和阅读每个领域,

如果使用默认序列化写出某些内容并且您希望通过Externalizable读取内容时遇到困难。 (或者说,它是不可能的。如果您尝试使用Externalizable读取使用默认方法序列化的对象,它只会抛出异常。)

如果您对输出完全没有控制权,那么您唯一的选择是保留该类的两个版本:使用旧版本的默认反序列化,然后转换为新版本。这个解决方案的优点是它可以保持"脏"代码在一个地方,与你漂亮干净的物品分开。

同样,除非你想做一些非常复杂的事情,你最好的选择是把旧班保留为"运输" bean并将您的代码实际使用的类重命名为其他类。

答案 1 :(得分:1)

如果您想阅读数据库中已有的内容,您唯一的选择就是让他们重新更改课程,并提醒您依赖课程定义,因为它是当班级被序列化时。仅仅实现你自己的readObject()调用就无法解决这个问题,如果这个类在别人的控制之下,那你无论如何也无法做到。

如果您准备丢弃现有数据,那么您可以从自定义序列化,writeReplace()/ readResolve(),Externalizable,...或其他机制(如XML)开始,有许多其他选择。

但是,如果你想让第三方在他们感觉到的时候改变事物,你总会遇到这种或那种问题。

BigDecimal to Long听起来像是一个逆行的步骤。

答案 2 :(得分:0)

在您的类中实现readObject和readObjectNoData方法。

使用ObjectInoutStream.readObject读取相应的类型并将其转换为新类型

有关详细信息,请参阅Serializable接口API。

更多细节

如果您控制序列化为blob的类的源,则只能轻松修复此问题。 如果你不控制这个班级, 那么你只有一些有限和困难的选择:

  1. 让控制方为您提供读取旧格式的类的版本并写入新格式。
  2. 编写自己的序列化形式(如在读取blob并将字节转换为类),这些形式可以读取旧格式并生成新版本的类。
  3. 编写您自己的类的版本(从类路径中删除另一个),它读取旧格式并生成一些中间形式(可能是JSON)。
  4. 接下来你必须做其中一个

    1. 说服那些blob技术很糟糕且应该废除的权力。使用当前的类更改作为evidance。几乎任何技术都比这更好。将JSON写入blob中的db更好。
    2. 停止依赖其他人的蹩脚课程。 (糟糕是一种我只能怀疑的判断,不知道,是真的)。而是创建一组表示数据库中的数据的类,并在写入数据库之前从外部控制的类转换为新的数据类。