How to replace Java default deserialization with my own readObject call?

Someone thought it would be nice to store objects in a database in a blob column using the default Java serialization methods. The structure of these objects is controlled by another group, and they change the field type from BigDecimal to Long, but the data in our database remains unchanged. Now we cannot read objects back because it calls ClassCastExceptions.

I tried to override it by writing my own readObject method, but this throws a StreamCorruptedException, because what was written by the writeObject method by default.

How to make my readObject call behave like Java by default? Is there a certain number of bytes that I can skip to get to my data?

+6
source share
3 answers

If you want to read what is already in your database, your only option is to get them to change the class again and establish some awareness that you are relying on the definition of the class, as it was when the class was serialized. Simply making your own call to readObject () cannot fix this, and if the class is under the control of others, you still cannot do it.

If you are ready to throw away existing data, you have many other options, starting with custom serialization, writeReplace () / readResolve (), Externalizable, ... or another mechanism such as XML.

But if you want third parties to change things when they feel that you will always have problems of one kind or another.

BigDecimal to Long is still like a retrograde step.

+1
source

Externalizable allows you to fully control serialization / deserialization. But this means that you are responsible for writing and reading each field,

When it becomes difficult, although it was once written out using default serialization, and you want to read it through Externalizable . (Or rather, this is not possible. If you try to read an object serialized using the default method using Externalizable , it will simply throw an exception.)

If you have absolutely no control over the exit, the only option is to save two versions of the class: use the default deserialization of the old version, and then convert it to the new one. The surface of this solution is that it keeps the "dirty" code in one place, separate from your nice and clean objects.

Again, if you do not want to do something really complicated, your best option is to save the old class as a "transport" bean and rename the class that your code really uses for something else.

+2
source

Inject the readObject and readObjectNoData methods into your class.

Read the corresponding type with ObjectInoutStream.readObject and convert it to a new type

See Serializable for more details.

More details

This can be easily fixed if you control the source of the class that was serialized in blob. If you do not control this class, then you have only a few limited and complex options:

  • Ask the control side to provide you with a version of the class that reads the old format and writes the new format.
  • Write you your own form of serialization (as you read blob and convert bytes to classes) that can read the old format and generate new versions of classes.
  • Write your own version of the class in question (delete another from the class path) that reads the old format and creates some intermediate form (possibly JSON).

Then you must do one of these

  • Convince yourself that the blob technique is crappy and it needs to be done away with. use the current class change as evidence. Almost any technique is better than this. Writing JSON in db in blob is better.
  • Stop depending on shitty classes from other people. (shitty is a solution that I can only suspect, but don't know). Instead, create a set of classes that represent data in the database and convert from external classes to new data classes before writing to the database.
0
source

Source: https://habr.com/ru/post/976438/


All Articles