manski's blog

.NET Serializers Comparison Chart

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
JSON.NET JSON.Net 6.0.5 JSON

Testing Framework

I wrote a small framework to do most of the tests in this article. You can get it here:

https://bitbucket.org/skrysmanski/dotnetserializertests

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 JSON.Net
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.
  • JSON.NET 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 JSON.Net
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 JSON.Net
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 JSON.Net
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 JSON.Net
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:

  • JSON.NET 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 JSON.Net
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 JSON.NET 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 JSON.NET 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 JSON.NET 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

9 comments

  1. Morten said:

    Another important factor that would be interesting is serialization and deserialization performance.

  2. Chris Marisic said:

    It would be great if you could add JIL to the list since it’s the fastest JSON serializer that was built specifically for usage on Stackoverflow

    • Sebastian Krysmanski (post author) replied:

      Maybe I will. But there are a lot of serializers out there that are also worth a look.

  3. Pingback: С миру по нитке, №12 | Things I think about

  4. Pingback: This Week On Channel 9 요약 정리 [10월 4,5주차] - Korea Evangelist - Site Home - MSDN Blogs

  5. milan said:

    which one faster serialization?

  6. astrowalker said:

    Thank you very much for this post. However it is good to note, that JSON serializers in .Net world are more limited due to their heritage — Javascript. So far I found two problems (uplifting ints and covering only piece of UInt64 range) but it is enough for me to rule JSON out.

  7. Pingback: Serialization - Saving Objects as Files - Kevin G. Agwaze

Leave a Reply

Your email address will not be published. Required fields are marked *