1

I would like to serialize and deserialize mixed data into XML. After some searches I found out that there were two ways of doing it: System.Runtime.Serialization.Formatters.Soap.SoapFormatter and System.Xml.Serialization.XmlSerializer. However, neither turned out to match my requirements, since:

  • SoapFormatter doesn't support serialization of generic types
  • XmlSerializer refuses to serialize types that implement IDictionary, not to mention that it's far less easy-to-use than "normal" serialization (e.g. see this SO question)

I'm wondering if there exists an implementation that doesn't have these limitations? I have found attempts (for example CustomXmlSerializer and YAXLib as suggested in a related SO question), but they don't seem to work either.

I was thinking about writing such serializer myself (though it certainly doesn't seem to be a very easy task), but then I find myself limited by the CLR, as I cannot create object instances of types that won't have a paramaterless constructor, even if I'm using reflection. I recall having read somewhere that implementations in System.Runtime.Serialization somehow bypass the normal object creation mechanism when deserializing objects, though I'm not sure. Any hints of how could this be done?
(See edit #3)

Could somebody please point me to the right direction with this?

Edit: I'm using .NET 3.5 SP1.

Edit #2: Just to be clear, I'd like a solution that is as much like using BinaryFormatter as possible, meaning that it should require the least possible extra code and annotations.

Edit #3: with some extra Googling, I found a .NET class called System.Runtime.Serialization.FormatterServices.GetUninitializedObject that actually can return "zeroed" objects of a specified type, which is great help in deserialization (if I get to implement it myself). I'd still like to find an existing solution though.

Community
  • 1
  • 1
ShdNx
  • 3,172
  • 5
  • 40
  • 47

5 Answers5

3

Ive had great success using the datacontractserializer class.here

Here's a pretty good article comparing serializers link

James South
  • 10,147
  • 4
  • 59
  • 115
2

Which version of the .NET Framework do you use? If you are on .NET 3.0 or higher, you may have luck with the DataContractSerializer or the NetDataContractSerializer. Both of those do serialize to XML but work quite different than the XmlSerializer.

hangy
  • 10,765
  • 6
  • 43
  • 63
  • I'm using .NET 3.5. I'll look into your suggestions and get back to you. Thanks! – ShdNx Jan 01 '11 at 20:06
  • I've edited my original post. My main problem with them is that they require a lot of new attributes to be added to the code, just to make it eiglible for serialization. I'd like to see a better solution, if possible. Thank you for your contribution anyway! – ShdNx Jan 01 '11 at 20:20
2

Depending on your .NET version and the complexity of your data, you may have luck using LINQ to XML to serialize:

internal class Inner
{
    public int Number { get; set; }
    public string NotNumber { get; set; }
}

internal class Outer
{
    public int ID { get; set; }
    public Dictionary<string, Inner> Dict { get; set; }
}

internal class Program
{
    private static void Main()
    {
        var data = new Outer
                       {
                           ID = 1,
                           Dict =
                               new Dictionary<string, Inner>
                                   {
                                       {
                                           "ABC",
                                           new Inner
                                               {
                                                   Number = 1,
                                                   NotNumber = "ABC1"
                                               }
                                           },
                                       {
                                           "DEF",
                                           new Inner
                                               {
                                                   Number = 2,
                                                   NotNumber = "DEF2"
                                               }
                                           }
                                   }
                       };

        var serialized =
            new XDocument(new XElement("Outer",
                                       new XAttribute("id", data.ID),
                                       new XElement("Dict",
                                                    from i in data.Dict
                                                    select
                                                        new XElement(
                                                        "Entry",
                                                        new XAttribute(
                                                            "key", i.Key),
                                                        new XAttribute(
                                                            "number",
                                                            i.Value.Number),
                                                        new XAttribute(
                                                            "notNumber",
                                                            i.Value.
                                                                NotNumber)))));

        Console.WriteLine(serialized);
        Console.Write("ENTER to finish: ");
        Console.ReadLine();
    }
}

Result:

<Outer id="1">
  <Dict>
    <Entry key="ABC" number="1" notNumber="ABC1" />
    <Entry key="DEF" number="2" notNumber="DEF2" />
  </Dict>
</Outer>

Deserializing:

private static Outer Deserialize(XDocument serialized)
{
    if (serialized.Root == null)
    {
        return null;
    }

    var outerElement = serialized.Root.Element("Outer");
    if (outerElement == null)
    {
        return null;
    }

    return new Outer
               {
                   ID =
                       int.Parse(
                           outerElement.Attribute("id").Value),
                   Dict =
                       outerElement.Element("Dict").
                           Elements("Entry").ToDictionary(
                               k => k.Attribute("key").Value,
                               v => new Inner
                                    {
                                       Number = Convert.ToInt32(v.Attribute("number").Value),
                                       NotNumber = v.Attribute("notNumber").Value
                                    })
               };
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Yes, I thought about that too, but as I wrote in my question, I don't know how to create "empty" objects, bypassing normal constructors? I'd like to come up with a general solution. – ShdNx Jan 01 '11 at 20:23
  • What's the problem with creating instances? You mean on deserialization? There is no magical serializer that does everythinjg for you. Give up that requirement, and you may be able to solve your problem. – John Saunders Jan 01 '11 at 20:26
  • What I meant is, that it is impossible to deserialize an object unless the type of that object has a paramterless constructor. So in order to write a general xml serializer, one needs to bypass constructors, and I was wondering how that was possible. – ShdNx Jan 01 '11 at 20:40
  • @ShdNx: It's not possible, so don't do it. Do what the XML Serializer does: generate the code to do the serialization and deserialization. Then, only the code generator needs to be generic - it can create code which is quite specific. – John Saunders Jan 01 '11 at 20:52
  • @John Saunders: see edit #3 - it's actually possible, it appears. I'm not completely sure I understand what you mean by "generate the code to do the serialization and deserialization". Oh, maybe you mean like xsd.exe? – ShdNx Jan 01 '11 at 23:03
  • I mean that the XML Serializer uses Reflection to look at the classes being serialized and then generates the code to serialize them. I suggest you do the same, though perhaps using different techniques. – John Saunders Jan 02 '11 at 00:56
  • Well, eventually I gave up trying different libraries and classes, and implemented it myself using LINQ to XML, similarly to your suggestion. Thank you for your help (all of you)! – ShdNx Jan 06 '11 at 12:19
1

Implementing custom XML serialization is not too bad. You could implement IXmlSerializable in the class that the normal XmlSerializer cannot support by default.

This CodeProject article has a good explanation of IXmlSerializable, and this blog post provides another look at more or less the same thing.

Adam Lear
  • 38,111
  • 12
  • 81
  • 101
-1

I suggest DataContractJsonSerializer, which gives shorter output and handles dictionaries better.

me22
  • 651
  • 3
  • 8
  • Yeah, sorry, I'm looking for XML solutions at the moment. I know that there are very handful libararies for JSON serialization, but I'd like to do this with XML. – ShdNx Jan 01 '11 at 21:01
  • Fair enough. I was hoping you didn't care about the format, since nothing in your question suggested it was more than an arbitrary choice and DataContractSerializer's XML isn't exactly the nicest for processing anyway. – me22 Jan 02 '11 at 03:51