views:

2600

answers:

12

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.

A: 

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.

Ben Hoffstein
Wasn't sure if mrbradleyt wanted to ignore some parts of the class graph when he said he didn't want to worry about it. In that case, not all of the attributes need be Serializable (NonSerializedAttribute can mark fields that should be excluded)
Hamish Smith
Yes, point taken. He also just clarified that he needs a non-binary format, so my solution wouldn't work for him.
Ben Hoffstein
The asker has specifically excluded binary serialization.
Andrei Rinea
+1  A: 

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

TraumaPony
More specifically, you can find all of Shawn's posts related to the intermediate serializer here:http://www.talula.demon.co.uk/blogindex.html#intermediateserializer
Joel Martinez
+1  A: 

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

ripper234
What class do you use?
mrbradleyt
I believe the usage of SOAP serialization is discouraged from NET 2.0. Actually it doesnt even handle generics.http://social.msdn.microsoft.com/Forums/en-US/netfxremoting/thread/ee4a7a63-290e-432f-bd45-44f4cb7a3467/
Santiago Palladino
Somewhere in Serialization.Formatters.Soap
ripper234
+2  A: 

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.

Ian Suttle
Can you please elaborate on the XmlArray attribute... i was having problems with Lists....
mrbradleyt
You don't really need the XmlArray attribute if you use sgen.The general pattern is to derive a separate class from List<YourObject>, and then serialize that insteadeg.[Serializable]public class YourObjectCollection : List<YourObject>{}However, I've found that even that isn't necessary
ilitirit
+1 ilitirit. Fixed an annoying problem I was having where I couldn't serialize a list without getting an extra set of tags wrapping it, so I couldn't ReadXml it into a DataSet.
Jared Updike
+1  A: 

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.

Jarrett Meyer
+3  A: 

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.

Ian Suttle
+1  A: 

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#)

ilitirit
A: 

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;
   }
}
Greg Ogle
+27  A: 

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.

James Newton-King
I have tried this, and it gave me better error results than the out of the box DataManinpulator JSON Serializer, however it still bombed because of a looping reference.Any tips? I'm building a messaging framework and don't have much control over the actual structure of any object.
mrbradleyt
Set the ReferenceLoopHandling property on the JsonSerializer to Ignore.
James Newton-King
I use JSON.Net - it totally rocks!!!!!
David Robbins
A: 

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).

Brody
A: 

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.

gpgemini
+1  A: 

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.

Slace