Faster serialization of `Serializable` objects

350 Views Asked by At

Our client/server app uses a NetDataContractSerializer to serialize arbitrary Serializable objects.

The output of BinaryFormatter would be somewhat smaller, performance however isn't really better.

Now smaller representations are possible (e.g. the outputs of XmlSerializer and DataContractSerializer, Json, Protocol Buffers, Thrift, etc.), that also happen to serialize and deserialize much faster.

However, in order to use those I'd have to go to every single one of the Serializable classes and add attributes and potentially change access levels of fields etc. Not only are these classes spread over many different internal projects, but our clients have their own dlls with Serializable classes which would have to be modified. In other words, a major undertaking.

Is there any other performance improvement, and potential size reduction (other than gzipping etc.), possible for Serializable objects?

2

There are 2 best solutions below

6
On

Many of those serializers do not require custom attributes - in fact some are specifically designed to recognize and work with SerializableAttribute. See, for example:

Json.NET example:

var settings = new JsonSerializerSettings
{ 
    TypeNameHandling = TypeNameHandling.All,
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
};
string serialized = JsonConvert.SerializeObject(obj, settings);
var deserialized = JsonConvert.DeserializeObject(serialized, settings);

UPDATE: You don't need to fork Json.NET to do the type instantiation. I'm using a custom JsonConverter as described in this article.

0
On

My conclusion after checking out Lars Kemmann's suggestions: There is no alternative to NetDataContractSerializer/BinaryFormatter that serializes and deserializes the in the same way.

I played around with Json.NET, and it kind of works, but as is often the case, the devil is in the details (see also my comments to Lars' answer):

Testing with real life objects it turned out my deserialized objects aren't 100% equivalent to the original ones, stemming from fields in super classes that don't get serialized. At least that is what it seems after a cursory check.

Protobuf-net is not an option either, as you

  1. have to register every (non-protobuf-annotated) type manually before serializing
  2. have to specify the exact type when deserializing
  3. it complains about classes that don't have a parameterless constructor