.NET Serializers Comparison Chart

30 Oct 2014 30 Oct 2014 9 min read .NET Serializers

There are many object serializers in C#/.NET but their details are often not so obvious, for example:

  • Does my class need a parameterless constructor?
  • Can I serialize private fields?
  • Can I serialize readonly fields?

So, I’ve compiled a comparison chart in this article that will compare the various serializers and their capabilities.

The following serializers will be compared:

Name Abbreviation Version Output Format
BinaryFormatter BF (.NET 4.5.1) Binary
DataContractSerializer DCS (.NET 4.5.1) XML
NetDataContractSerializer NDCS (.NET 4.5.1) XML
XmlSerializer XMLSer (.NET 4.5.1) XML
DataContractJsonSerializer DCJS (.NET 4.5.1) JSON
Newtonsoft.JSON Newtonsoft 6.0.5 JSON

Testing Framework 

I wrote a small framework to do most of the tests in this article.

Note

Unfortunately, the code got lost when BitBucket nuked its Mercurial projects.

You may also want to have a look at it when some feature isn’t clear to you.

General Capabilities 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Serialized size of 1 example object (bytes) 322 253 456 273 54 57
Serialized size of 500 example objects (bytes) 18.583 68.679 76.397 81.687 27.501 33.396
Can serialize unattributed class no yes yes yes yes yes
Supports [Serializable] and [NonSerializable] yes yes yes no yes yes
Supports [DataContract] no yes yes no yes yes
Can mix attributed and unattributed members - yes yes - yes yes
Respects [OnDeserialized] and related (unattributed) - yes yes no yes yes
Respects [OnDeserialized] and related ([Serializable]) yes yes yes - yes yes
Respects [OnDeserialized] and related ([DataContract]) - yes yes - yes yes

Notes on features:

  • A dash (-) means “not applicable”. For example, BinaryFormatter can only serialize classes that are attributed with [Serializable]. So, it doesn’t make sense to check whether it calls the parameterless constructor on a [DataContract] class.
  • Can serialize unattributed class: Serializers that can’t serialize unattributed classes are a bad choice if you want to serialize types that are not attributed (with [Serializable] or [DataContract]) and for which you don’t have access to the code (e.g. some library types).
  • For [OnDeserialization], see Version-Tolerant Serialization Callbacks.
    • Tests were done with the attributed methods being private.

Notes on serializers:

  • The XmlSerializer treats all classes as if they were not attributed.
  • Newtonsoft.JSON serializer settings used:
    • ReferenceLoopHandling = ReferenceLoopHandling.Serialize
    • PreserveReferencesHandling = PreserveReferencesHandling.Objects (without this, the serializer can’t detect reference loops and creates stack overflows)

Class/Type Features 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Can serialize private class (unattributed) - no no no no yes
Can serialize private class ([Serializable]) yes yes yes - yes yes
Can serialize private class ([DataContract]) - yes yes - yes yes
Needs parameterless constructor (unattributed) - yes yes yes yes no
Needs parameterless constructor ([Serializable]) no no no - no no
Needs parameterless constructor ([DataContract]) - no no - no no
Can deserialize class with private constructor (unattributed) - no no no no no
Can deserialize class with private constructor ([Serializable]) yes yes yes - yes no
Can deserialize class with private constructor ([DataContract]) - yes yes - yes no
Calls parameterless constructor (unattributed) - yes yes yes yes yes
Calls parameterless constructor ([Serializable]) no no no - no yes
Calls parameterless constructor ([DataContract]) - no no - no yes

Notes on features:

Fields and Properties 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Can serialize private fields (Unattributed) - no no no no no
Can serialize private fields ([Serializable]) yes yes yes - yes no
Can serialize private fields ([DataContract]) - yes yes - yes yes
Can serialize readonly fields (Unattributed) - no no no no no
Can serialize readonly fields ([Serializable]) yes yes yes - yes no
Can serialize readonly fields ([DataContract]) - yes yes - yes yes
Calls property getter and setter when serializing (unattributed) - yes yes yes yes yes
Calls property getter and setter when serializing ([Serializable]) no no no - no yes
Calls property getter and setter when serializing ([DataContract]) - yes yes - yes yes
Calls private setter when deserializing (unattributed) - no no no no no
Calls private setter when deserializing ([Serializable]) - - - - - no
Calls private setter when deserializing ([DataContract]) - yes yes - yes yes

Deserialization Type Restrictions 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Can deserialize arbitrary types (unattributed) - no yes no no no
Can deserialize arbitrary types ([Serializable]) yes no yes - no no
Can deserialize arbitrary types ([DataContract]) - no yes - no no
Serialized root type information assm ns assm name none none
Can deserialize to different assembly (unattributed) - yes no yes yes yes
Can deserialize to different assembly ([Serializable]) no yes no - yes yes
Can deserialize to different assembly ([DataContract]) - yes no - yes yes
Can deserialize to different namespace (unattributed) - no no yes yes yes
Can deserialize to different namespace ([Serializable]) no no no - yes yes
Can deserialize to different namespace ([DataContract] w/o attrib) - no no - yes yes
Can deserialize to different namespace ([DataContract] w/ attrib) - yes no - yes yes
Can deserialize to different class name (unattributed) - no no no yes yes
Can deserialize to different class name ([Serializable]) no no no - yes yes
Can deserialize to different class name ([DataContract] w/o attrib) - no no - yes yes
Can deserialize to different class name ([DataContract] w/ attrib) - yes no - yes yes

Notes on features:

  • If Can deserialize arbitrary types is “yes”, it means that the serializer doesn’t require a “known types” list. If it’s “no”, all types need to be statically available (i.e. child class instead of base class) and/or a known types list must be provided.
  • Serialized root type information: what information about the root type is serialized. Possible values: assm = assembly, namespace and type name, ns = namespace and type name, name = type name, none = nothing
    • This means, the more information is stored, the more restrictive the deserialization is. For example, for assm you can’t change any type information about the deserialized object, while ns at least allows you to change the assembly of the type when deserializing (if name and namespace remain the same).
  • [DataContract] w/ attrib means that the attribute Name or Namespace is specified respectively. [DataContract] w/o attrib means that this attribute is not specified (i.e. their values are inherited from the type the data contract is defined on).

Reference Support 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Supports references (unattributed) - no yes no no yes
Supports references ([Serializable]) yes no yes - no yes
Supports references ([DataContract(IsReference=false)) - no yes - no yes
Supports references ([DataContract(IsReference=true)) - yes yes - no yes
Supports references loops (unattributed) - - yes - - yes
Supports references loops ([Serializable]) yes - yes - - yes
Supports references loops ([DataContract]) - yes yes - - yes
Can detected references loops (unattributed) - yes yes yes yes yes
Can detected references loops ([Serializable]) yes yes yes - yes yes
Can detected references loops ([DataContract(IsReference=false)]) - yes yes - yes yes
Can detected references loops ([DataContract(IsReference=true)]) - yes yes - yes yes

Notes on features:

  • Supports references means that, if the same object (i.e. same reference) exists multiple times in the object tree, it won’t be deserialized as two different objects (two different references).

Notes on serializers:

  • Newtonsoft.JSON serializer: If in the settings, ReferenceLoopHandling is set to Serialize but PreserveReferencesHandling remains None (which is the default), the serializer won’t detect reference loops. Instead it’ll cause a stack overflow.

Other 

Feature BF DCS NDCS XMLSer DCJS Newtonsoft
Can serialize readonly collections yes yes yes no yes yes
Serializes enums as bin name name name int int
Can deserialize unknown enum values yes no no no yes yes
Requires [EnumMember] attributes no no no no no no
Can serialize static members no no no no no yes/no

Notes on features:

  • Values for Serializes enums as are: “name”, “int”, and “bin”(ary).
  • For more information about [EnumMember], see Enumeration Types in Data Contracts.
  • The test for serializing static members is included here only for completeness reasons and because some tests depend on static fields not being serialized (which is what one would expect).

Notes on serializers:

  • The Newtonsoft.JSON serializer does serialize static fields/properties attributed with [DataMember]. This phenomenon is tracked as issue #399.

Conclusion 

The BinaryFormatter is the most versatile serializer because it has the least serialization restriction - except for two: 1. Both sides (i.e. serializing and deserializing side) need to use the same assembly. 2. You can’t serialize unattributed types. When used for internal communication between software components the first limitation may not be a problem. The second limitation, however, may be a deal-breaker.

The DataContractSerializer is more forgiving when deserializing types from a different assembly (version) and it can serialize unattributed types. The first advantage comes with a price though: You can’t deserialize arbitrary types, i.e. you need to provide the serializer with a list of known types. It also doesn’t allow you to deserialize unknown enum values (even though C# supports this). In our software project this is a constant source for problems because we get our enum values from an outside source (server).

The NetDataContractSerializer mixes pros and cons of both the BinaryFormatter and the DataContractSerializer. It can deserialize arbitrary types and thus requires the same assembly on both side (like with the BinaryFormatter), but also supports serializing unattributed types (like the DataContractSerializer). It also can’t deserialize unknown enum values.

The XmlSerializer is the least powerful serializer in that it doesn’t support serializing anything fancy (e.g. private fields, readonly fields, …). I don’t see any benefit in using this serializer when compared to the other serializers available.

The DataContractJsonSerializer is a JSON serializer that just serializes what’s in the official JSON standard. Thus, it doesn’t support serializing references but other than that has the same serialization capabilities as the DataContractSerializer. Since JSON doesn’t contain any type information, this serializer (together with the Newtonsoft.JSON serializer) has the least restrictions on what type to deserialize to. On the other hand however, this means that you can’t deserialize arbitrary types - and since no type names are stored in JSON, you can’t even provide a known types list.

The Newtonsoft.JSON serializer is the other JSON serializer but is vastly superior to the DataContractJsonSerializer as it supports more features - like references and type names. Unfortunately it can’t deserialize arbitrary types if they’re in a list (i.e. List<object>), even if type names are enabled. Also it can’t deserialize classes that don’t have public constructors and also no non-public parameterless constructor.

History 

  • 2014-10-27 : Published
  • 2014-10-30 : Added results for classes with non-public constructors