How to serialize derived classes in a Xml?

10,057

You have to tell the serializer about the derived types

[XmlInclude(typeof(FooA))]
[XmlInclude(typeof(FooB))]
public abstract class Foo
{
    public abstract int X { get; set; }
}

This is one of the choice .Net exceptions that are truly helpful. If you look at the InnerException, you will see

The type FooA was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

UPDATE

Based on your comment about many derived types in different modules, you can also specify derived types at runtime when creating the serializer rather than at compile time:

How to add XmlInclude attribute dynamically

Share:
10,057
Darf Zon
Author by

Darf Zon

Updated on June 04, 2022

Comments

  • Darf Zon
    Darf Zon almost 2 years

    Imagine this is my scenario:

    public abstract class Foo
    {
        public abstract int X { get; set; }
    }
    
    public class FooA : Foo
    {
        public override int X { get; set; }
        public int Y { get; set; }
    }
    
    public class FooB : Foo
    {
        public override int X { get; set; }
        public int Z { get; set; }
    }
    

    This is a service where I've got some objects to serialize.

    public class FooService
    {
        public List<Foo> GetModels()
        {
            return new List<Foo>()
            {
                new FooA() { X = 3, Y = 6 },
                new FooB() { X = 5, Z = 10 }
            };
        }
    }
    

    And this is the method where I can't serialize my objects, it throws an exception. I want to serialize derived classes.

        private void SerializeObjects()
        {
            FooService service = new FooService();
            var a = service.GetModels();
    
            XmlSerializer x = new XmlSerializer(a.GetType());
            TextWriter writer = new StreamWriter("A.xml");
    
            x.Serialize(writer, a);
            writer.Close();
        }
    
    • dee-see
      dee-see about 12 years
      What is the exception? What have you tried?
    • Eric J.
      Eric J. about 12 years
      What's the exception text? I bet it's complaining about known types and telling you what to do about it.
    • Darf Zon
      Darf Zon about 12 years
      @Vache this is my error: There was an error generating the XML document.
    • dreza
      dreza about 12 years
      There's no XML Attribute declarations on any of those classes. You have to tell the serializer what to serialise by decorating properties and attributes of Foo, FooA, FooB etc
    • Eric J.
      Eric J. about 12 years
      And the inner exception tells you to "The type FooA was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically." :-)
    • Darf Zon
      Darf Zon about 12 years
      @EricJ. It works :), allow me to make clear my situation. I've got a library where it has ´Foo´, and another modules contains FooA and FooB. I mean, I need to create many modules and I don't prefer put those Includes.. what might I do?
    • L.B
      L.B about 12 years
      @DarfZon Use some other serializers like Json.Net
    • Eric J.
      Eric J. about 12 years
      @L.B: Json.Net can handle types that are not statically known? DataContractSerializer cannot... would surprise me if Json.Net can.
    • Eric J.
      Eric J. about 12 years
      @DarfZon: Added more info to the answer based on "many modules"
    • L.B
      L.B about 12 years
      @EricJ. This is the output [{"X":3,"Y":6},{"X":5,"Z":10}] of JsonConvert.SerializeObject(service.GetModels())