Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialization backwards compatibility

I am trying to deserialize "SomeClass" with an older version of an application. I get this below exception

System.Runtime.Serialization.SerializationException: The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.

Deserialization throws exception when I serialize version 0.9 and try to deserialize using version 0.8. I thought the OptionalField attribute would do the trick, but it didn't.

// Version 0.8
[Serializable()]
class Foo{
  Bar b;
} 

// Version 0.9
[Serializable()]
class Foo{
  Bar b;
  [OptionalField]
  Zoo z;
}

Given that I cannot change version 0.8, how should I add more state to Foo object such that previous versions can deserialize whatever they can?

Any pointer will be really appreciated.

Update 1 Bar and Zoo are other classes which are serializable and contains Hashtables and other serializable stuff. Everything is serializable in those classes. Also, I don't have any struts.

like image 682
karephul Avatar asked Mar 21 '11 18:03

karephul


People also ask

What is meant by deserialization?

Deserialization is the opposing process which takes data from a file, stream or network and rebuilds it into an object. Serialized objects can be structured in text such as JSON, XML or YAML. Serialization and deserialization are safe, common processes in web applications.

What is serialization vs deserialization?

Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory.

What is deserialization in software?

This process converts and changes the data organization into a linear format that is needed for storage or transmission across computing devices.

What does it mean to deserialize data?

The process whereby a lower-level format (e.g. that has been transferred over a network, or stored in a data store) is translated into a readable object or other data structure.


1 Answers

First, never NEVER use the CLR's serialization functions for anything that resembles long-term storage. We make that mistake usually once, put objects in a blob database field and pat ourselves in the back thinking we're clever. And then the CLR gets a patch or our assemblies change versions and you're screwed. So don't do it.

If you still want to do it, the best way to manage the problem is to create your own SerializationBinder that looks something like this:

public sealed class CustomBinder : SerializationBinder {

    public override Type BindToType(string assemblyName, string typeName) {

        Type typeToDeserialize = null;

        if (typeName.IndexOf("SomeType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.NewType);
        }
        else if (typeName.IndexOf("SomeOtherType") != -1) {
            typeToDeserialize = typeof(Foo.Bar.Bax.SomeOtherNewType);
        }
        else {
            // ... etc
        }

        return typeToDeserialize;
    }
}

Set the Binder property of the formatter you're using prior to deserializing so that it overrides the defaults.

Note that I'm not offering a drop-in solution here, I'm recommending how to solve the problem. Once you've converted out of whatever you're doing, investigate other serialization technologies like protobuf, or write your own. Either way you should never rely on the CLR for long-term serialization support.

like image 84
kprobst Avatar answered Oct 05 '22 13:10

kprobst