ShouldSerialize*() vs *Specified Conditional Serialization Pattern










16















I am aware of both of the ShouldSerialize* pattern and the *Specified pattern and how they work, but is there any difference between the two?



Are there any "gotchas" using one method vs the other when certain things should be serialized conditionally?



This question is specific to the usage of XmlSerializer, but general information regarding this topic is welcome as well.



There is very little information on this topic out there, so it may be because they perform the exact same purpose and it's a style choice. However, it seems strange that the .NET implementers would analyze the class via reflection and look for either/both patterns to determine how the generated serializer behaves since it slows down the generation of the serializer unless it's just a backwards compatibility artifact.



EDIT: For those unfamiliar with the two patterns if either the *Specified property or ShouldSerialize* method returns true, then that property is serialized.



public string MyProperty get; set; 

//*Specified Pattern
[XmlIgnore]
public bool MyPropertySpecified get return !string.IsNullOrWhiteSpace(this.MyProperty);

//ShouldSerialize* Pattern
public bool ShouldSerializeMyProperty()

return !string.IsNullOrWhiteSpace(this.MyProperty);










share|improve this question
























  • What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

    – Sinatr
    Jun 15 '16 at 14:53






  • 1





    @Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

    – JNYRanger
    Jun 15 '16 at 15:20







  • 2





    This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

    – Hans Passant
    Jun 15 '16 at 15:29






  • 1





    @HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

    – JNYRanger
    Jun 15 '16 at 15:33
















16















I am aware of both of the ShouldSerialize* pattern and the *Specified pattern and how they work, but is there any difference between the two?



Are there any "gotchas" using one method vs the other when certain things should be serialized conditionally?



This question is specific to the usage of XmlSerializer, but general information regarding this topic is welcome as well.



There is very little information on this topic out there, so it may be because they perform the exact same purpose and it's a style choice. However, it seems strange that the .NET implementers would analyze the class via reflection and look for either/both patterns to determine how the generated serializer behaves since it slows down the generation of the serializer unless it's just a backwards compatibility artifact.



EDIT: For those unfamiliar with the two patterns if either the *Specified property or ShouldSerialize* method returns true, then that property is serialized.



public string MyProperty get; set; 

//*Specified Pattern
[XmlIgnore]
public bool MyPropertySpecified get return !string.IsNullOrWhiteSpace(this.MyProperty);

//ShouldSerialize* Pattern
public bool ShouldSerializeMyProperty()

return !string.IsNullOrWhiteSpace(this.MyProperty);










share|improve this question
























  • What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

    – Sinatr
    Jun 15 '16 at 14:53






  • 1





    @Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

    – JNYRanger
    Jun 15 '16 at 15:20







  • 2





    This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

    – Hans Passant
    Jun 15 '16 at 15:29






  • 1





    @HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

    – JNYRanger
    Jun 15 '16 at 15:33














16












16








16


3






I am aware of both of the ShouldSerialize* pattern and the *Specified pattern and how they work, but is there any difference between the two?



Are there any "gotchas" using one method vs the other when certain things should be serialized conditionally?



This question is specific to the usage of XmlSerializer, but general information regarding this topic is welcome as well.



There is very little information on this topic out there, so it may be because they perform the exact same purpose and it's a style choice. However, it seems strange that the .NET implementers would analyze the class via reflection and look for either/both patterns to determine how the generated serializer behaves since it slows down the generation of the serializer unless it's just a backwards compatibility artifact.



EDIT: For those unfamiliar with the two patterns if either the *Specified property or ShouldSerialize* method returns true, then that property is serialized.



public string MyProperty get; set; 

//*Specified Pattern
[XmlIgnore]
public bool MyPropertySpecified get return !string.IsNullOrWhiteSpace(this.MyProperty);

//ShouldSerialize* Pattern
public bool ShouldSerializeMyProperty()

return !string.IsNullOrWhiteSpace(this.MyProperty);










share|improve this question
















I am aware of both of the ShouldSerialize* pattern and the *Specified pattern and how they work, but is there any difference between the two?



Are there any "gotchas" using one method vs the other when certain things should be serialized conditionally?



This question is specific to the usage of XmlSerializer, but general information regarding this topic is welcome as well.



There is very little information on this topic out there, so it may be because they perform the exact same purpose and it's a style choice. However, it seems strange that the .NET implementers would analyze the class via reflection and look for either/both patterns to determine how the generated serializer behaves since it slows down the generation of the serializer unless it's just a backwards compatibility artifact.



EDIT: For those unfamiliar with the two patterns if either the *Specified property or ShouldSerialize* method returns true, then that property is serialized.



public string MyProperty get; set; 

//*Specified Pattern
[XmlIgnore]
public bool MyPropertySpecified get return !string.IsNullOrWhiteSpace(this.MyProperty);

//ShouldSerialize* Pattern
public bool ShouldSerializeMyProperty()

return !string.IsNullOrWhiteSpace(this.MyProperty);







c# .net serialization xml-serialization xmlserializer






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 15 '16 at 15:38







JNYRanger

















asked Jun 15 '16 at 14:43









JNYRangerJNYRanger

4,60793460




4,60793460












  • What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

    – Sinatr
    Jun 15 '16 at 14:53






  • 1





    @Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

    – JNYRanger
    Jun 15 '16 at 15:20







  • 2





    This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

    – Hans Passant
    Jun 15 '16 at 15:29






  • 1





    @HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

    – JNYRanger
    Jun 15 '16 at 15:33


















  • What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

    – Sinatr
    Jun 15 '16 at 14:53






  • 1





    @Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

    – JNYRanger
    Jun 15 '16 at 15:20







  • 2





    This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

    – Hans Passant
    Jun 15 '16 at 15:29






  • 1





    @HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

    – JNYRanger
    Jun 15 '16 at 15:33

















What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

– Sinatr
Jun 15 '16 at 14:53





What is "*Specified pattern"? Do you mean [XmlIgnore] attribute?

– Sinatr
Jun 15 '16 at 14:53




1




1





@Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

– JNYRanger
Jun 15 '16 at 15:20






@Sinatr No. If you create a gettable boolean property named <Propertyname>Specified that returns true if it should be serialized it appears to do the same thing as the ShouldSerialize* pattern (obviously you put an [XmlIgnore] attribute on this property.)

– JNYRanger
Jun 15 '16 at 15:20





2




2





This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

– Hans Passant
Jun 15 '16 at 15:29





This is intentionally undocumented, they want you to use attributes instead. This "feature" probably snuck into XmlSerializer because of an early version of the Winforms designer or an unfinished plan to move to something equivalent to XAML. That's a guess.

– Hans Passant
Jun 15 '16 at 15:29




1




1





@HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

– JNYRanger
Jun 15 '16 at 15:33






@HansPassant Interesting. The *Specified pattern is briefly mentioned here in the Controlling Generated XML section of the remarks in the XmlSerializer class documentation, but nothing on the ShouldSerialize*() pattern. Unfortunately, attributes don't work when the serialization is conditional.

– JNYRanger
Jun 15 '16 at 15:33













2 Answers
2






active

oldest

votes


















23














The intent of the propertyNameSpecified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:



  • The <element> element is involved.


  • minOccurs is zero.

  • The maxOccurs attribute dictates a single instance.

  • The data type converts to a value type.

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a propertyNameSpecified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, propertyNameSpecified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.



The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:



public class ExampleClass

[XmlElement]
public decimal Something get; set;

[XmlIgnore]
public bool SomethingSpecified get; set;



The following schema will be generated, and vice versa:



<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
<xs:complexType name="ExampleClass">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:schema>


Note that, while xsd.exe is documented only to generate automatically a propertyNameSpecified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.



You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:



  • Nullables are used to support the xsi:nil="true" attribute instead. See Xsi:nil Attribute Binding Support.

  • Nullables were not introduced until .Net 2.0, so maybe it was too late to use them for this purpose?

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.



Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.



(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing propertyNameSpecified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)



Support for the ShouldSerializePropertyName() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?



Because it is a method not a property, it lacks the "gotchas" of the propertyNameSpecified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:



  • Json.NET


  • protobuf-net (which claims to supports both patterns.)

So, which pattern to use?



  1. If xsd.exe generates a propertyNameSpecified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".


  2. Otherwise, use the ShouldSerializePropertyName() pattern. It has fewer gotchas and may be more widely supported.






share|improve this answer

























  • Thanks for the detailed answer!

    – JNYRanger
    Jun 15 '16 at 18:49


















3














To add to the very detailed answer by @dbc, I ran into an issue with managing serialization in derived classes. In my situation I had a base class and a derived class where a Prop property was overridden.



public class BaseClass

public virtual string Prop get; set;


public class Derived: BaseClass

public string Comp1 get; set;
public string Comp2 get; set;
public override string Prop get => Comp1 + Comp2; set



Since the Prop property in the derived class is calculated, for the Derived class I wanted to serialize Comp1 and Comp2 but not Prop. It turns out that setting the XmlIgnore attribute on the Prop property in the Derived class does not work and Prop is serialized anyway.



I also tried to add a ShouldSerializeProp method and a PropSpecified property in the Derived class, but neither work. I tried setting breakpoints to see if they are called and they are not.



It turns out that the XmlSerializer is looking at the original class where the Prop property appears for the first time in the class hierarchy to decide whether to serialize a property or not. To be able to control serialization in a derived class, first I had to add a virtual ShouldSerializeProp in the Base class.



public class Base

.....
public virtual bool ShouldSerializeProp() return true;



Then I could override the ShouldSerializeProp in the Derived class and return false.



public class Derived: Base

.....
public override bool ShouldSerializeProp() return false;



This pattern allows different derived classes to choose what properties from the parent class they serialize. Hope this helps.






share|improve this answer























  • Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

    – JNYRanger
    Jan 10 '18 at 14:50










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37838640%2fshouldserialize-vs-specified-conditional-serialization-pattern%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









23














The intent of the propertyNameSpecified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:



  • The <element> element is involved.


  • minOccurs is zero.

  • The maxOccurs attribute dictates a single instance.

  • The data type converts to a value type.

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a propertyNameSpecified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, propertyNameSpecified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.



The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:



public class ExampleClass

[XmlElement]
public decimal Something get; set;

[XmlIgnore]
public bool SomethingSpecified get; set;



The following schema will be generated, and vice versa:



<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
<xs:complexType name="ExampleClass">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:schema>


Note that, while xsd.exe is documented only to generate automatically a propertyNameSpecified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.



You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:



  • Nullables are used to support the xsi:nil="true" attribute instead. See Xsi:nil Attribute Binding Support.

  • Nullables were not introduced until .Net 2.0, so maybe it was too late to use them for this purpose?

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.



Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.



(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing propertyNameSpecified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)



Support for the ShouldSerializePropertyName() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?



Because it is a method not a property, it lacks the "gotchas" of the propertyNameSpecified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:



  • Json.NET


  • protobuf-net (which claims to supports both patterns.)

So, which pattern to use?



  1. If xsd.exe generates a propertyNameSpecified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".


  2. Otherwise, use the ShouldSerializePropertyName() pattern. It has fewer gotchas and may be more widely supported.






share|improve this answer

























  • Thanks for the detailed answer!

    – JNYRanger
    Jun 15 '16 at 18:49















23














The intent of the propertyNameSpecified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:



  • The <element> element is involved.


  • minOccurs is zero.

  • The maxOccurs attribute dictates a single instance.

  • The data type converts to a value type.

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a propertyNameSpecified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, propertyNameSpecified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.



The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:



public class ExampleClass

[XmlElement]
public decimal Something get; set;

[XmlIgnore]
public bool SomethingSpecified get; set;



The following schema will be generated, and vice versa:



<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
<xs:complexType name="ExampleClass">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:schema>


Note that, while xsd.exe is documented only to generate automatically a propertyNameSpecified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.



You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:



  • Nullables are used to support the xsi:nil="true" attribute instead. See Xsi:nil Attribute Binding Support.

  • Nullables were not introduced until .Net 2.0, so maybe it was too late to use them for this purpose?

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.



Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.



(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing propertyNameSpecified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)



Support for the ShouldSerializePropertyName() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?



Because it is a method not a property, it lacks the "gotchas" of the propertyNameSpecified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:



  • Json.NET


  • protobuf-net (which claims to supports both patterns.)

So, which pattern to use?



  1. If xsd.exe generates a propertyNameSpecified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".


  2. Otherwise, use the ShouldSerializePropertyName() pattern. It has fewer gotchas and may be more widely supported.






share|improve this answer

























  • Thanks for the detailed answer!

    – JNYRanger
    Jun 15 '16 at 18:49













23












23








23







The intent of the propertyNameSpecified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:



  • The <element> element is involved.


  • minOccurs is zero.

  • The maxOccurs attribute dictates a single instance.

  • The data type converts to a value type.

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a propertyNameSpecified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, propertyNameSpecified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.



The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:



public class ExampleClass

[XmlElement]
public decimal Something get; set;

[XmlIgnore]
public bool SomethingSpecified get; set;



The following schema will be generated, and vice versa:



<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
<xs:complexType name="ExampleClass">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:schema>


Note that, while xsd.exe is documented only to generate automatically a propertyNameSpecified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.



You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:



  • Nullables are used to support the xsi:nil="true" attribute instead. See Xsi:nil Attribute Binding Support.

  • Nullables were not introduced until .Net 2.0, so maybe it was too late to use them for this purpose?

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.



Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.



(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing propertyNameSpecified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)



Support for the ShouldSerializePropertyName() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?



Because it is a method not a property, it lacks the "gotchas" of the propertyNameSpecified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:



  • Json.NET


  • protobuf-net (which claims to supports both patterns.)

So, which pattern to use?



  1. If xsd.exe generates a propertyNameSpecified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".


  2. Otherwise, use the ShouldSerializePropertyName() pattern. It has fewer gotchas and may be more widely supported.






share|improve this answer















The intent of the propertyNameSpecified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:



  • The <element> element is involved.


  • minOccurs is zero.

  • The maxOccurs attribute dictates a single instance.

  • The data type converts to a value type.

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a propertyNameSpecified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, propertyNameSpecified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.



The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:



public class ExampleClass

[XmlElement]
public decimal Something get; set;

[XmlIgnore]
public bool SomethingSpecified get; set;



The following schema will be generated, and vice versa:



<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
<xs:complexType name="ExampleClass">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:schema>


Note that, while xsd.exe is documented only to generate automatically a propertyNameSpecified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.



You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:



  • Nullables are used to support the xsi:nil="true" attribute instead. See Xsi:nil Attribute Binding Support.

  • Nullables were not introduced until .Net 2.0, so maybe it was too late to use them for this purpose?

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.



Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.



(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing propertyNameSpecified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)



Support for the ShouldSerializePropertyName() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?



Because it is a method not a property, it lacks the "gotchas" of the propertyNameSpecified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:



  • Json.NET


  • protobuf-net (which claims to supports both patterns.)

So, which pattern to use?



  1. If xsd.exe generates a propertyNameSpecified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".


  2. Otherwise, use the ShouldSerializePropertyName() pattern. It has fewer gotchas and may be more widely supported.







share|improve this answer














share|improve this answer



share|improve this answer








edited May 8 '18 at 19:38









NH.

88311129




88311129










answered Jun 15 '16 at 18:20









dbcdbc

53.8k869122




53.8k869122












  • Thanks for the detailed answer!

    – JNYRanger
    Jun 15 '16 at 18:49

















  • Thanks for the detailed answer!

    – JNYRanger
    Jun 15 '16 at 18:49
















Thanks for the detailed answer!

– JNYRanger
Jun 15 '16 at 18:49





Thanks for the detailed answer!

– JNYRanger
Jun 15 '16 at 18:49













3














To add to the very detailed answer by @dbc, I ran into an issue with managing serialization in derived classes. In my situation I had a base class and a derived class where a Prop property was overridden.



public class BaseClass

public virtual string Prop get; set;


public class Derived: BaseClass

public string Comp1 get; set;
public string Comp2 get; set;
public override string Prop get => Comp1 + Comp2; set



Since the Prop property in the derived class is calculated, for the Derived class I wanted to serialize Comp1 and Comp2 but not Prop. It turns out that setting the XmlIgnore attribute on the Prop property in the Derived class does not work and Prop is serialized anyway.



I also tried to add a ShouldSerializeProp method and a PropSpecified property in the Derived class, but neither work. I tried setting breakpoints to see if they are called and they are not.



It turns out that the XmlSerializer is looking at the original class where the Prop property appears for the first time in the class hierarchy to decide whether to serialize a property or not. To be able to control serialization in a derived class, first I had to add a virtual ShouldSerializeProp in the Base class.



public class Base

.....
public virtual bool ShouldSerializeProp() return true;



Then I could override the ShouldSerializeProp in the Derived class and return false.



public class Derived: Base

.....
public override bool ShouldSerializeProp() return false;



This pattern allows different derived classes to choose what properties from the parent class they serialize. Hope this helps.






share|improve this answer























  • Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

    – JNYRanger
    Jan 10 '18 at 14:50















3














To add to the very detailed answer by @dbc, I ran into an issue with managing serialization in derived classes. In my situation I had a base class and a derived class where a Prop property was overridden.



public class BaseClass

public virtual string Prop get; set;


public class Derived: BaseClass

public string Comp1 get; set;
public string Comp2 get; set;
public override string Prop get => Comp1 + Comp2; set



Since the Prop property in the derived class is calculated, for the Derived class I wanted to serialize Comp1 and Comp2 but not Prop. It turns out that setting the XmlIgnore attribute on the Prop property in the Derived class does not work and Prop is serialized anyway.



I also tried to add a ShouldSerializeProp method and a PropSpecified property in the Derived class, but neither work. I tried setting breakpoints to see if they are called and they are not.



It turns out that the XmlSerializer is looking at the original class where the Prop property appears for the first time in the class hierarchy to decide whether to serialize a property or not. To be able to control serialization in a derived class, first I had to add a virtual ShouldSerializeProp in the Base class.



public class Base

.....
public virtual bool ShouldSerializeProp() return true;



Then I could override the ShouldSerializeProp in the Derived class and return false.



public class Derived: Base

.....
public override bool ShouldSerializeProp() return false;



This pattern allows different derived classes to choose what properties from the parent class they serialize. Hope this helps.






share|improve this answer























  • Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

    – JNYRanger
    Jan 10 '18 at 14:50













3












3








3







To add to the very detailed answer by @dbc, I ran into an issue with managing serialization in derived classes. In my situation I had a base class and a derived class where a Prop property was overridden.



public class BaseClass

public virtual string Prop get; set;


public class Derived: BaseClass

public string Comp1 get; set;
public string Comp2 get; set;
public override string Prop get => Comp1 + Comp2; set



Since the Prop property in the derived class is calculated, for the Derived class I wanted to serialize Comp1 and Comp2 but not Prop. It turns out that setting the XmlIgnore attribute on the Prop property in the Derived class does not work and Prop is serialized anyway.



I also tried to add a ShouldSerializeProp method and a PropSpecified property in the Derived class, but neither work. I tried setting breakpoints to see if they are called and they are not.



It turns out that the XmlSerializer is looking at the original class where the Prop property appears for the first time in the class hierarchy to decide whether to serialize a property or not. To be able to control serialization in a derived class, first I had to add a virtual ShouldSerializeProp in the Base class.



public class Base

.....
public virtual bool ShouldSerializeProp() return true;



Then I could override the ShouldSerializeProp in the Derived class and return false.



public class Derived: Base

.....
public override bool ShouldSerializeProp() return false;



This pattern allows different derived classes to choose what properties from the parent class they serialize. Hope this helps.






share|improve this answer













To add to the very detailed answer by @dbc, I ran into an issue with managing serialization in derived classes. In my situation I had a base class and a derived class where a Prop property was overridden.



public class BaseClass

public virtual string Prop get; set;


public class Derived: BaseClass

public string Comp1 get; set;
public string Comp2 get; set;
public override string Prop get => Comp1 + Comp2; set



Since the Prop property in the derived class is calculated, for the Derived class I wanted to serialize Comp1 and Comp2 but not Prop. It turns out that setting the XmlIgnore attribute on the Prop property in the Derived class does not work and Prop is serialized anyway.



I also tried to add a ShouldSerializeProp method and a PropSpecified property in the Derived class, but neither work. I tried setting breakpoints to see if they are called and they are not.



It turns out that the XmlSerializer is looking at the original class where the Prop property appears for the first time in the class hierarchy to decide whether to serialize a property or not. To be able to control serialization in a derived class, first I had to add a virtual ShouldSerializeProp in the Base class.



public class Base

.....
public virtual bool ShouldSerializeProp() return true;



Then I could override the ShouldSerializeProp in the Derived class and return false.



public class Derived: Base

.....
public override bool ShouldSerializeProp() return false;



This pattern allows different derived classes to choose what properties from the parent class they serialize. Hope this helps.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 10 '18 at 6:48









TibiTibi

463




463












  • Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

    – JNYRanger
    Jan 10 '18 at 14:50

















  • Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

    – JNYRanger
    Jan 10 '18 at 14:50
















Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

– JNYRanger
Jan 10 '18 at 14:50





Great point @Tibi. I asked this question a few years ago, but what I've learned since then is to always make serialization classes like this as sealed unless you know in advance that there is going to be a derived classes due to needing virtual methods.

– JNYRanger
Jan 10 '18 at 14:50

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f37838640%2fshouldserialize-vs-specified-conditional-serialization-pattern%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Top Tejano songwriter Luis Silva dead of heart attack at 64

政党

天津地下鉄3号線