Question

I would like to serialize and deserialize objects without having to worry about the entire class graph.

Flexibility is key. I would like to be able to serialize any object passed to me without complete attributes needed throughout the entire object graph.

That means that Binary Serialization is not an option as it only works with the other .NET Platforms. I would also like something readable by a person, and thus decipherable by a management program and other interpreters.

I've found problems using the DataContract, JSON, and XML Serializers.

  • Most of these errors seem to center around Serialization of Lists/Dictionaries (i.e. XML Serializable Generic Dictionary).
  • "Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer."

Please base your answers on actual experiences and not theory or reading of an article.

Was it helpful?

Solution

Have you considered serializing to JSON instead of XML?

Json.NET has a really powerful and flexible serializer that has no problems with Hashtables/generic dictionaries and doesn't require any particular attributes. I know because I wrote it :)

It gives you heaps of control through various options on the serializer and it allows you to override how a type is serialized by creating a JsonConverter for it.

In my opinion JSON is more human readable than XML and Json.NET gives the option to write nicely formatted JSON.

Finally the project is open source so you can step into the code and make modifications if you need to.

OTHER TIPS

If I recall it works something like this with a property:

[XmlArray("Foo")]
[XmlArrayItem("Bar")]
public List<BarClass> FooBars
{ get; set; }

If you serialized this you'd get something like:

<Foo>
    <Bar />
    <Bar />
</Foo>

Of course, I should probably defer to the experts. Here's more info from MS: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

Let me know if that works out for you.

From your requirements it sounds like Xml Serialization is best.

What sort of problems do you have with collections when serializing? If you're referring to not knowing what attributes to use on a List or something similar, you might try the XmlArray attribute on your property. You can definitely serialize a collection.

The IntermediateSerializer in the XNA Framework is pretty damn cool. You can find a bunch of tutorials on using it at http://blogs.msdn.com/shawnhar

SOAP Serialization worked well for me, even for objects not marked with [Serializable]

You'll have problems with collection serialization if objects in the collection contain any reference to other objects in the same collection. If any type of dual-pointing exists, you end up creating a multi-map that cannot be serialized. On every problem I've ever had serializing a custom collection, it was always because of some added functionality that I needed that worked fine as part of a "typical" client-server application, and then failed miserably as part of a consumer-provider-server application.

Put all the classes you want to serialize into a separate assembly, and then use the sgen tool to generate a serialization assembly to serialize to XML. Use XML attributes to control serialization.

If you need to customize the serialization assembly (and you will need that to support classes that aren't IXmlSerializable and classes that contain abstract nodes), then instruct sgen to dump the source code into a separate file and then add it to your solution. Then you can modify it as necessary.

http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx

FWIW, I've managed to serialize the entire AdsML Framework (over 400 classes) using this technique. It did require a lot of manual customization, but there's no getting around that if you consider the size of the framework. (I used a separate tool to go from XSD to C#)

I agree that the DataContract-based serialization methods (to JSON, XML, etc) is a bit more complex than I'd like.

If you're trying to get JSON check out http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

It's part of the MS AJAX extensions. Admittedly it is flagged as Obsolete in .NET 3.5 but ScottGu mentions in his blog comment here (http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx#4301973) that he's not sure why and it should be supported for a bit longer.

The simplest thing to do is mark your objects with the Serializable attribute and then use a binary formatter to handle the serialization. The entire class graph shouldn't be a problem provided that any contained objects are also marked as Serializable.

Perhaps a more efficient route would be to serialize using the BinaryFormatter

As copied from http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Serializer
{
   public Serializer()
   {
   }

   public void SerializeObject(string filename,
                  ObjectToSerialize objectToSerialize)
   {
      Stream stream = File.Open(filename, FileMode.Create);
      BinaryFormatter bFormatter = new BinaryFormatter();
      bFormatter.Serialize(stream, objectToSerialize);
      stream.Close();
   }

   public ObjectToSerialize DeSerializeObject(string filename)
   {
      ObjectToSerialize objectToSerialize;
      Stream stream = File.Open(filename, FileMode.Open);
      BinaryFormatter bFormatter = new BinaryFormatter();
      objectToSerialize =
         (ObjectToSerialize)bFormatter.Deserialize(stream);
      stream.Close();
      return objectToSerialize;
   }
}

For interoperability we have always used Xml Serialisation and made sure our class was designed from the ground up to do it correctly.

We create an XSD schema document and generate a set of classes from that using XSD.exe. This generates partial classes so we then create a set of corresponding partial classes to add the extra methods we want to help us populate the classes and use them in our application (as they are focused on serialising and deserialising and are a bit difficut to use sometimes).

You should use the NetDataContractSerializer. It covers any kind of object graph and supports generics, lists, polymorphism (the KnownType attribute is not needed here), recursion and etc. The only drawback is that you have to mark all you classes with [Serializable] / [DataContract] attributes, but experience shows that you have to do some sort of manual fine-tuning anyway since not all members should be persisted. Also it serializes into an Xml, though its readability is questionable.

We had the same requirements as yours and chose this solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top