65

This is one i struggled with for ages so thought I'd document somewhere. (Apologies for asking and answering a question.)

(C# .net 2.0) I had a class that was being serialized by XmlSerializer, I added a new public property however it wasn't being included in the output XML.

It's not mentioned in the docs anywhere I could find, but public properties must have a set as well as a get to be serialized! I guess this is because it assumes that if you're going to serialize then you'll want to deserialize from the same file, so only serializes properties that have both a set and a get.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Rory
  • 40,559
  • 52
  • 175
  • 261

7 Answers7

106

As mentioned, most properties must have both a getter and setter; the main exception to this is lists - for example:

private readonly List<Foo> bar = new List<Foo>();
public List<Foo> Bar {get { return bar; } } // works fine

which will work fine; however, if XmlSerializer finds a setter - it demands that it is public; the following will not work:

public List<Foo> Bar {get; private set;} // FAIL

Other reasons it might not serialize:

  • it isn't public with get and set (or is readonly for a field)
  • it has a [DefaultValue] attribute, and is with that value
  • it has a public bool ShouldSerializeFoo() method that returned false
  • it has a public bool FooSpecified {get;set;} property or field that returned false
  • it is marked [XmlIgnore]
  • it is marked [Obsolete]

Any of these will cause it not to serialize

Gregor Slavec
  • 4,814
  • 1
  • 26
  • 24
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Although I do have some properties with just a get. They're also marked with XmlArray and XmlArrayItem attributes, so I guess that's why they get away with out a set. – Rory Feb 22 '09 at 23:46
  • 2
    In some cases, a property that returns a collection doesn't need a set, but it must be initialized in the constructor... It is the case for collections with no public constructor. But this behavior seems a bit inconsistent to me... – Thomas Levesque Jun 28 '09 at 18:37
  • I've never noticed that, thanks Thomas; I will investigate ;-p – Marc Gravell Jun 29 '09 at 07:13
  • 2
    It will also not serialize if the property is marked `[Obsolete]`. – Nick Whaley Jul 16 '13 at 15:33
  • 1
    Had a getter but no setter...wow that was irritating, appreciate the post. – afreeland Aug 26 '13 at 17:55
  • @afreeland actually, I may have mis-spoke; for lists you don't need a setter, but if one is there it must not be private. I will update. – Marc Gravell Aug 26 '13 at 18:37
  • 1
    i never understand why having a public getter only will not be serialised?? – user384080 Feb 28 '14 at 05:26
  • 3
    @user384080 most serializers expect to be used **in both directions** - i.e. both to serialize and deserialize. If there is no `set`, it won't be able to recreate the object during deserialization, because it can't assign a value. Now, sometimes serializers can work around this, and sometimes they just serialize it without promising to deserialize; however, `XmlSerializer` chooses the "ignore the property" approach. – Marc Gravell Feb 28 '14 at 12:28
  • that "FooSpecified" note just saved me from a similar issue, thanks for including that. – msulis Dec 18 '14 at 23:30
  • 1
    Another one for the list: When using Xamarin.Mac, the Linker might remove properties. The Attribute [Foundation.Preserve(AllMembers=true)] prevents this. – dube Sep 26 '17 at 13:18
  • 3
    The [Foo]Specified serializer "gotcha" had me stumped. Consuming 3rd party XML, with very bad documentation, which had a *AmountPaid* public decimal property and *AmountPaidSpecified* public bool property. The default value for AmountPaidSpecified is false since it's a bool. So, AmountPaid was never getting serialized! By setting the AmountPaidSpecified to true, voila!, AmountPaid gets serialized. – iCode Feb 20 '19 at 14:13
  • I've just been bitten by this, because the lack of the `set` method on my properties. When I added it, the properties began to appear in te output file. I just want to Xml `Serialize`, I do no need to `Deserialize`. Does it make any sense that I need to declare the setter? In my head, this is **utterly unlogic**. – sergiol Jun 29 '22 at 16:48
  • @MarcGravell You saved my sanity with this: it has a [DefaultValue] attribute, and is with that value. I don't see that anywhere in the documentation and it caused me an issue with some auto generated classes from .net core for consuming soap services. If anyone else has an issue with public properties that have a gettor and settor not serializing make sure they don't have a DefaultValueAttriubte set. – JamesL Jan 31 '23 at 18:55
7

The point about getter+setter is made in the 3rd paragraph on the "Intro to Xml Serialization" page. It's actually in a call-out box. Can't miss it!

Intro-to-XML Serialization http://www.freeimagehosting.net/uploads/2f04fea2db.png

(having a little too much fun with Freeimagehosting.net)

Cheeso
  • 189,189
  • 101
  • 473
  • 713
5

Also properties that return null are not serialized!

anonymous
  • 645
  • 5
  • 9
  • 1
    Ah, but nullable type properties that return null are! I have this here public int? GroupTypeId property which got serialised into this here XML - – Jon Jul 12 '13 at 16:37
5

if you don't want to implement proper Setters (because maybe you are neither wanting to deserialize or change an objects value) you can just use dummy setters like this set { }, so that the XMLSerializer works, but nothing happens if you use the Setter...

i.E.

public string ID { get { return _item.ID.ToString(); } set { } }
JonSchn
  • 93
  • 2
  • 5
  • 3
    this could potentially be an issue if a junior programmer use this setter property and thinking it's setting the value. Still prefer to have "throw new exception... " – user384080 Feb 28 '14 at 05:29
3

And if your class inherits a list and also has its own members, only the elements of the list get serialized. The data present in your class members is not captured. Took some time figuring out this!

Nanda
  • 1,038
  • 2
  • 16
  • 33
3

One more thing to add about serialization of collections:

The XmlSerializer ignores collections of interfaces!

And by that I mean ignore. While you will get an exception for a line like:

public IFoo Foo { get; set; }

you will not get an exception for:

public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } }
NobodysNightmare
  • 2,992
  • 2
  • 22
  • 33
0

You can implement the IXmlSerializer and do the serialization manually, and benefit from serializing properties, and vice versa, deserializing them using constructors / private field assignment.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632